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

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

对于那些无法从代码中删除的人,它会循环遍历从 PartitionMap 继承的缓冲区中的可变长度描述符。

对于那些有关的人,partitionMapLength总是返回运行它的系统支持的长度。我正在遍历的数据符合 UDF 规范。

有帮助吗?

解决方案

我经常使用这些模板:

    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

其他提示

Casting是唯一的方法,无论是char *或intptr_t还是其他类型的,然后是你的最终类型。

你当然可以保留两个变量:一个 char * 来逐步执行缓冲区,一个 PartitionMap * 来访问它。让事情变得更加清晰。

for (char *ptr = ??, pm = (PartitionMap *)ptr ; index > 0 ; --index)
{
    ptr += pm->partitionMapLength;
    pm = (PartitionMap *)ptr;
}
return pm;

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

x86架构中,为数不多的架构之一(即使它是最受欢迎的架构)也能让您轻松获得它。但是,即使您正在为Windows编写,也需要考虑此问题 - Win64确实强制执行对齐要求。

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

您可以使用Windows上的 __ unaligned 之类的编译器扩展轻松解决此问题:

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;

必须完成转换,但它使代码几乎不可读。为了便于阅读,请将其隔离在静态内联函数中。

让我感到困惑的是为什么你有'partitionMapLength'的字节数?

如果它是在“partitionMap”单位中会不会更好,因为你还是投了它?

PartitionMap *pmBase(reinterpret_cast<PartitionMap *>(partitionMaps));
PartitionMap *pm;
...
pm = pmBase + index; // just guessing about your 'index' variable here

C和C ++都允许您通过指针和 ++ 遍历数组:

#include <iostream>

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

为此,添加指针定义为获取存储在指针中的内存地址,然后添加sizeof,无论类型是添加值的类型。例如,在我们的示例中, ++ ptr 1 * sizeof(int)添加到 ptr 中存储的内存地址。

如果你有一个指向某个类型的指针,并希望从该位置推进特定数量的字节,那么唯一的方法是转换为 char * (因为 sizeof (char)被定义为one)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top