在以下代码行中,我需要将指针pm
调整为其字段之一的字节偏移量。是否有更好/更简单的方法来执行此操作,而不是从char *
和PartitionMap *
不断地来回转换,以便指针算法仍然有效?
PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
pm = (PartitionMap *)(((char *)pm) + pm->partitionMapLength);
}
return pm;
对于那些无法从代码中删除的人,它会在从PartitionMap
继承的缓冲区中循环遍历可变长度描述符。
对于那些有关的人,partitionMapLength总是返回运行它的系统支持的长度。我正在遍历的数据符合UDF规范。
答案 0 :(得分:5)
Casting是唯一的方法,无论是char *或intptr_t还是其他类型的,然后是你的最终类型。
答案 1 :(得分: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
答案 2 :(得分:3)
你当然可以保留两个变量:一个char *
来逐步通过缓冲区,一个PartitionMap *
来访问它。让事情变得更加清晰。
for (char *ptr = ??, pm = (PartitionMap *)ptr ; index > 0 ; --index)
{
ptr += pm->partitionMapLength;
pm = (PartitionMap *)ptr;
}
return pm;
答案 3 :(得分:1)
正如其他人所说,你需要演员,但你可以隐藏宏观或功能中的丑陋。但是,要记住的另一件事是对齐要求。在大多数处理器上,您不能简单地将指针增加到任意数量的字节,并将结果转换回指向原始类型的指针,而不会因为未对齐而通过新指针访问结构。
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;
答案 4 :(得分:0)
必须完成转换,但它使代码几乎不可读。为了便于阅读,请将其隔离在static inline
函数中。
答案 5 :(得分:0)
让我感到困惑的是为什么你有'partitionMapLength'的字节数?
如果它是在“partitionMap”单位中会不会更好,因为你还是投了它?
PartitionMap *pmBase(reinterpret_cast<PartitionMap *>(partitionMaps));
PartitionMap *pm;
...
pm = pmBase + index; // just guessing about your 'index' variable here
答案 6 :(得分:0)
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)
被定义为是一个)。