9

In the current draft standard (and C++17), this is written about 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.

I wonder, what is the difference whether the conversion is pointer-interconvertible or not? Is there a case, when casting a void * to something pointer-interconvertible actually changes the pointer value? What is the intent of this distinction?

For completeness 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.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
geza
  • 28,403
  • 6
  • 61
  • 135

2 Answers2

8

You may misunderstand the term "pointer value". The term is defined in [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.

So you can see the term "pointer value" in the standard is a very abstract term. Even if two pointer values represent the same address, they may have different values. The example in cppreference demonstrates the concept of "pointer value" nicely:

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"
Community
  • 1
  • 1
xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • "_describe the strict aliasing rules formally_" Do the so called "strict aliasing rules" have any formal purpose? – curiousguy Jul 11 '18 at 03:27
  • @curiousguy [This answer](https://stackoverflow.com/a/99010/5376789) shows how these rules benefit the compiler/optimizer. – xskxzr Jul 11 '18 at 04:02
  • @xskxzr: your answer was very helpful for me. It should get more visibility... May ask I you, how did you learn the exact semantics of pointers? Teacher? Book? Reading and interpreting the standard? – geza Jul 29 '18 at 19:30
  • @geza This is one of the changes in C++17. I have paid attention to these changes thus know this semantic change. – xskxzr Jul 30 '18 at 03:28
3

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

No, the standard clearly states

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

What is the intent of this distinction?

I would think the distinction comes not in the value of the pointer but in it's semantics. The important part is that you end up with a pointer to the object b (which inter-covertible with the original object pointed). This is a stronger and more specific guarantee than "the original value remains unchanged", even though in this case the original value also remains unchanged.

Stronger guarantee: the resulting pointer points to an actual object (not just to an address in memory)

A more specific guarantee: this object is specified: it is the object b which is pointer interchangeable with the original object pointed by the pointer.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
bolov
  • 72,283
  • 15
  • 145
  • 224
  • I don't think "the result is a pointer to b" implies "pointer points to an actual object". [An object pointer can be explicitly converted to an object pointer of a different type.](http://eel.is/c++draft/expr.post#expr.reinterpret.cast-7) – llllllllll Jul 10 '18 at 06:28
  • @liliscent your quote is about `reinterpret_cast` – bolov Jul 10 '18 at 06:31
  • I meant pointer type doesn't imply the existence of an actual object. Converting from one type to another is always possible, no matter whether there is an actual object. – llllllllll Jul 10 '18 at 06:34
  • @liliscent that's exactly my point. And the quote gives this extra guarantee: "the result is a pointer to b" – bolov Jul 10 '18 at 06:36
  • Hmm, what is the difference between pointing to an actual object vs. pointing to an address, which happens to be the address of an actual object? – geza Jul 10 '18 at 06:39
  • 2
    On some architectures a pointer can be more than just an address. Changing the type of a pointer can change it's bit pattern even if it does not change the address pointed to. – Richard Critten Jul 10 '18 at 06:42
  • That makes sense, "pointer to b" does imply an actual object b. +1 – llllllllll Jul 10 '18 at 06:52
  • @geza a) For purposes of garbage collection b) For purposes of optimization they are different. – Passer By Jul 10 '18 at 06:55
  • @PasserBy: does that mean, that somehow I can create a `A *` pointer to an address, where an `A` object does exist, but it doesn't point to the object, just to the address? – geza Jul 10 '18 at 06:59
  • @PasserBy: hmm, maybe my last question relates to this: https://stackoverflow.com/questions/47653305/is-there-a-semantic-difference-between-the-return-value-of-placement-new-and-t . It is strange to accept, that a pointer points to an address of an object, yet it doesn't point to the object itself, just to its address. – geza Jul 10 '18 at 07:03
  • @geza What you said is correct. In the cases where there is no pointer-interconvertibility, the casted pointer has a different type but points to the original object, regardless if its value representation coincided with some address of an object of the new type. – Passer By Jul 10 '18 at 07:14
  • Does it mean you're allowed to create (POD) objects using static_cast (provided you take care of alignment)? – rustyx Jul 10 '18 at 07:27
  • @rustyx No. This has been discussed over and beyond. – Passer By Jul 10 '18 at 07:30
  • Thanks, bolov! I've upvoted your answer, but I'll accept xskxzr's answer, because he/she clarified how one should think about pointers. Now, I understand your answer as well, but xskxzr's answer was the one which opened my eyes. – geza Jul 10 '18 at 09:11
  • Therefore the last sentence, "*Otherwise, the pointer value is unchanged by the conversion.*", is useless, no? – rustyx Jul 10 '18 at 09:12
  • @rustyx: in C++14, that conversion was unspecified. Now they say that such conversions don't change pointer value. So I think that sentence does have its place. – geza Jul 10 '18 at 09:17