是否有任何reinterpret_cast改变指针值的真实例子?

时间:2010-07-21 11:38:33

标签: c++ compiler-construction casting

根据C ++标准,reinterpret_cast指针T*指向其他类型指针Q* can change or not change the pointer value,具体取决于实现。

我非常感兴趣 - 它有一个C ++实现的真实示例,其中使用reinterpret_cast转换指向其他指针类型的指针会更改指针吗?什么和为什么在那里改变了?

5 个答案:

答案 0 :(得分:6)

请注意,当标准声明它可以或不可能执行某些操作时,并不意味着存在任何具有该行为的当前实现,只是它们可以执行。

我能想到的最接近的是一个架构,其中硬件需要类型对齐,以及一个决定在需要时纠正对齐的实现。类似的东西:

aligned8 var;
aligned1 *p = reinterpret_cast<aligned1*>(&var);
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1]

可能要求a为有效指针,它必须寻址8的内存位置,而具有较小对齐要求的参数q可以指向任何内存地址。

答案 1 :(得分:2)

class A1 { int a1; };
class A2 { int a2; };

class B: public A1, public A2 { };

#define DBG(val)  cout << #val << ": " << val << endl

// test code
B b;
DBG(&b);                                           // prints 0x42

void *p_blank = &b;
DBG(p_blank);                                      // prints 0x42
A2 *p_a2 = &b; 
DBG(p_a2);                                         // prints 0x46
void *p_reinterpreted = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted);                              // prints 0x42
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted2);                             // prints 0x42

A2 *p_a2 = &b表示给我指向B对象中的A2对象reinterpret_cast<A2*>(&b)表示给我指向b的指针并将其视为A2指针。 此reinterpret_cast的结果具有“指向A2的指针”类型,因此在分配给void *变量(或A2 *变量)时不会产生警告。

答案 2 :(得分:1)

最可能的麻烦来源是向量机器,其中标量运算是根据向量定义的,标量指针由指向向量的指针和向量的索引组成。从历史上看,最初的Cray架构是这样的,它引起了令人头疼的问题。现在你可能会在GPU上看到类似的东西,但我无法指出一些具体的东西。

最可能的影响是截​​断,因为目标指针类型缺少用于指定索引部分的位。 C ++ 11通过允许任何指针类型为reinterpret_cast,只要它们具有相同的对齐要求,就可以朝这个方向点头。允许通过严格对齐“归零”的位不存在。

  

可以将对象指针显式转换为对象指针   不同的类型。当“指向T1的指针”类型的prvalue v是   转换为“指向cv T2的指针”类型,如果T1和T2都是标准布局,则结果为static_cast<cv T2*>(static_cast<cv void*>(v))   类型(3.9)并且T2的对齐要求不比更严格   那些T1,或任何一种类型都是无效的。转换类型的prvalue   “指向T1的指针”到“指向T2的指针”(其中T1和T2为   对象类型以及T2的对齐要求为否   比T1更严格,并回到原来的类型产生   原始指针值。任何其他此类指针的结果   转换未指定。

答案 3 :(得分:1)

我不认为C ++与C指针转换的问题有很大不同。从this answer我只引用其中一个例子:

  

Data General的Eclipse MV系列有三种架构支持的指针格式(字,字和位指针),其中两个由C编译器使用:char*void*的字节指针,和其他一切的词指针

这表明reinterpret_cast<Word_Aligned_Type*>(char*)可能会失去对单词中指向哪个字符/字节的感觉,使操作不可逆转。

答案 4 :(得分:0)

Reinterpret_cast永远不会返回不同的地址 - 需要复制确切的地址。

在多重继承的情况下,如David Rodriguez所说,取其中一个碱基的地址可能会返回一个与第一个碱基地址有偏移的地址。 Reinterpret_cast将返回该偏移地址,但如果您将其视为向上转发地址,那么地狱将随之而来。

对于upcasting,static_cast可以返回与给定地址不同的地址。如果您拥有的地址是其中一个基地,并且该地址与第一个基址的偏移量相同,则static_cast将返回该上升对象的有效地址,该地址等于第一个基地的地址,因此不相等传递给指针。

简而言之:reinterpret_cast始终为您提供相同的地址。 Static_cast和dynamic_cast可以返回不同的地址,例如在涉及多重继承的某些情况下。

static_cast和dynamic_cast之间的区别在于static_cast不检查你给它的指针是否是演员的正确对象,所以在调用之前一定要确定。