首页 > 解决方案 > static_cast 的指针值

问题描述

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

“指向cv1 void 的指针”类型的纯右值可以转换为“指向cv2 T 的指针”类型的纯右值,其中 T 是对象类型,而 cv2 与cv1具有相同的 cv 限定或大于cv1的 cv 限定。如果原始指针值表示内存中一个字节的地址A,并且A不满足T的对齐要求,那么得到的指针值是未指定的。否则,如果原始指针值指向对象a,并且存在 T 类型的对象b(忽略 cv 限定)与a指针可互转换,则结果是指向b的指针. 否则,指针值不会因转换而改变。

我想知道,转换是否可以指针互转换有什么区别?有没有一种情况,当将 avoid *转换为指针可互转换的东西实际上会改变指针值?这种区分的目的是什么?

对于完整性指针可互换

如果满足以下条件,两个对象 a 和 b 是指针可互转换的:

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

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

标签: c++language-lawyerc++17void-pointersstatic-cast

解决方案


您可能会误解术语“指针值”。该术语在[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"

推荐阅读