1

在下面的代码行中,我需要pm通过其中一个字段中的字节偏移量来调整指针。有没有更好/更简单的方法来做到这一点,而不是不断地来回转换char *PartitionMap *这样指针算术仍然有效?

PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
    pm = (PartitionMap *)(((char *)pm) + pm->partitionMapLength);
}
return pm;

对于那些无法从代码中理解的人,它正在循环通过缓冲区中的可变长度描述符,该缓冲区继承自PartitionMap.

同样对于相关人员,partitionMapLength 始终返回运行该系统的系统支持的长度。我正在遍历的数据符合UDF规范。

4

7 回答 7

5

强制转换是唯一的方法,无论是转换为 char* 还是 intptr_t 或其他类似类型,然后转换为您的最终类型。

于 2009-10-26T04:09:48.673 回答
5

我经常为此使用这些模板:

    template<typename T>
    T *add_pointer(T *p, unsigned int n) {
            return reinterpret_cast<T *>(reinterpret_cast<char *>(p) + n);
    }

    template<typename T>
    const T *add_pointer(const T *p, unsigned int n) {
            return reinterpret_cast<const T *>(reinterpret_cast<const char *>(p) + n);
    }

它们维护类型,但向它们添加单个字节,例如:

T *x = add_pointer(x, 1); // increments x by one byte, regardless of the type of x
于 2009-10-26T04:32:31.933 回答
3

您当然可以只保留两个变量:a 单char *步通过缓冲区和 aPartitionMap *访问它。让它更清楚发生了什么。

for (char *ptr = ??, pm = (PartitionMap *)ptr ; index > 0 ; --index)
{
    ptr += pm->partitionMapLength;
    pm = (PartitionMap *)ptr;
}
return pm;
于 2009-10-26T05:23:05.497 回答
1

正如其他人提到的那样,您需要演员表,但您可以在宏或函数中隐藏丑陋。但是,要记住的另一件事是对齐要求。在大多数处理器上,您不能简单地将指向类型的指针增加任意数量的字节并将结果转换回指向原始类型的指针,而不会由于未对齐而通过新指针访问结构时出现问题。

x86 架构是少数几个可以让您摆脱它的架构之一(即使它是最流行的)。然而,即使你是为 Windows 编写的,你也需要考虑这个问题——Win64 确实强制了对齐要求。

因此,即使partitionMapLength通过指针访问成员也可能会使您的程序崩溃。

__unaligned您可能可以使用Windows 上的编译器扩展轻松解决此问题:

PartitionMap __unaliged *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
    pm = (PartitionMap __unaligned *)(((char *)pm) + pm->partitionMapLength);
}
return pm;

或者您可以将可能未对齐的数据复制到正确对齐的结构中:

PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));

char* p = reinterpret_cast<char*>( pm);

ParititionMap tmpMap;
for ( ; index > 0 ; --index)
{

    p += pm->partitionMapLength;

    memcpy( &tmpMap, p, sizeof( newMap));
    pm = &tmpMap;
}

// you may need a more spohisticated copy to return something useful
size_t siz = pm->partitionMapLength;
pm = reinterpret_cast<PartitionMap*>( malloc( siz));
if (pm) {
    memcpy( pm, p, siz);
}
return pm;
于 2009-10-26T06:37:10.310 回答
0

强制转换必须完成,但它使代码几乎不可读。为了可读性,将其隔离在一个static inline函数中。

于 2009-10-26T04:28:34.937 回答
0

令我困惑的是为什么你有'partitionMapLength'以字节为单位?

如果它在'partitionMap'单位中会不会更好,因为你无论如何都会施放它?

PartitionMap *pmBase(reinterpret_cast<PartitionMap *>(partitionMaps));
PartitionMap *pm;
...
pm = pmBase + index; // just guessing about your 'index' variable here
于 2009-10-26T04:40:27.597 回答
0

C 和 C++ 都允许您通过指针遍历数组,并且++

#include <iostream>

int[] arry = { 0, 1, 2, 3 };
int* ptr = arry;
while (*ptr != 3) {
    std::cout << *ptr << '\n';
    ++ptr;
}

为此,添加到指针被定义为获取存储在指针中的内存地址,然后添加任何类型的大小乘以添加的值。例如,在我们的示例中,++ptr添加1 * sizeof(int)到存储在ptr.

如果您有一个指向类型的指针,并且想要从该位置推进特定数量的字节,那么这样做的唯一方法是强制转换为char*(因为sizeof(char)定义为一个)。

于 2009-10-26T06:43:25.627 回答