static_cast'指针值

static_cast'd pointer value

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

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion.

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

完整性pointer interconvertible:

Two objects a and b are pointer-interconvertible if:

  • (4.1) they are the same object, or
  • (4.2) one is a union object and the other is a non-static data member of that object ([class.union]), or
  • (4.3) one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or
  • (4.4) there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast.

Is there a case, when casting a void * to something pointer-interconvertible actually changes the pointer value?

不,标准明确规定

If two objects are pointer-interconvertible, then they have the same address

What is the intent of this distinction?

我认为区别不在于指针的值,而在于它的语义。重要的部分是你最终得到一个指向 对象 b 的指针(它与指向的原始对象相互隐藏)。这是比 "the original value remains unchanged" 更强大和更具体的保证,即使在这种情况下原始值也保持不变。

更强的保证:结果指针指向一个实际对象(不仅仅是内存中的地址)

一个更具体的保证:这个对象被指定:它是对象b,它与指针指向的原始对象是指针可互换的。

您可能对“指针值”一词有误解。该术语在 [basic.compound]/3:

中定义

Every value of pointer type is one of the following:

  • a pointer to an object or function (the pointer is said to point to the object or function), or

  • a pointer past the end of an object ([expr.add]), or

  • the null pointer value ([conv.ptr]) for that type, or

  • an invalid pointer value.

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively.

所以你可以看到标准中的术语“指针值”是一个非常抽象的术语。即使两个指针值表示相同的地址,它们也可能具有不同的值。 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"