static_cast'd指针值

gez*_*eza 9 c++ void-pointers static-cast language-lawyer c++17

在当前的标准草案(和C++ 17)中,是关于static_casting的void *:

类型"指针的prvalue CV1空隙"可以被转换成类型的prvalue"指针CV2 T",其中T是一个对象类型和CV2是相同的CV-资格,或更大的CV-资格比,CV1.如果原始指针值表示存储器中字节的地址A而A不满足T的对齐要求,则未指定结果指针值.否则,如果原始指针值指向对象a,并且存在类型为T(忽略cv-qualification)的对象b,该对象b是指针可互换,则结果是指向b的指针.否则,转换指针值不变.

我想知道,转换是指针可互换的有什么区别?有没有一种情况,当一个void *东西指向一个指针 - 可互换实际上改变指针值?这种区别的意图是什么?

对于完整性指针可互换:

如果出现以下情况,则两个对象a和b是指针可互换的:

  • (4.1)它们是同一个对象,或者
  • (4.2)一个是union对象,另一个是该对象的非静态数据成员([class.union]),或者
  • (4.3)一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象([class. mem]),或
  • (4.4)存在对象c,使得a和c是指针可互换的,并且c和b是指针可互换的.

如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过reinterpret_cast从指向另一个的指针获得指向一个对象的指针.

xsk*_*xzr 8

您可能会误解"指针值"这个术语.该术语在[basic.compound]/3中定义:

指针类型的每个值都是以下之一:

  • 的指针的对象或函数(指针被说成指向的对象或功能),或

  • 指针超过对象的末尾([expr.add]),或

  • 该类型的空指针值([conv.ptr]),或

  • 一个无效的指针值.

指针类型的值是指向或超过对象末尾的指针,表示对象占用的内存中的第一个字节的地址([intro.memory])或存储结束后的内存中的第一个字节分别被对象占用.

所以你可以看到标准中的术语"指针值"是一个非常抽象的术语.即使两个指针值表示相同的地址,它们也可能具有不同的值.cppreference中的示例很好地演示了"指针值"的概念:

struct S1 { int a; } s1;
struct S2 { int a; private: int b; } s2; // not standard-layout
union U { int a; double b; } u = {0};
int arr[2];

int* p1 = reinterpret_cast<int*>(&s1); // value of p1 is "pointer to s1.a" because s1.a
                                       // and s1 are pointer-interconvertible

int* p2 = reinterpret_cast<int*>(&s2); // value of p2 is unchanged by reinterpret_cast and
                                       // is "pointer to s2". 

int* p3 = reinterpret_cast<int*>(&u);  // value of p3 is "pointer to u.a": u.a and u are
                                       // pointer-interconvertible

double* p4 = reinterpret_cast<double*>(p3); // value of p4 is "pointer to u.b": u.a and u.b
                                            // are pointer-interconvertible because both
                                            // are pointer-interconvertible with u

int* p5 = reinterpret_cast<int*>(&arr); // value of p5 is unchanged by reinterpret_cast and
                                        // is "pointer to arr"
Run Code Online (Sandbox Code Playgroud)