c++undefined-behaviorreinterpret-castpointer-conversion

Is casting `the address of a pointer to a struct` to `the address of a struct whos first member is a pointer to the struct` UB?


  1. I have a struct called Node whose first member is Node* p_next
  2. I have a pointer to the first node called p_head
  3. I want to cast &p_head which is of type Node** to a Node*, and store it in p_node_before_head. This is so I can treat *p_node_before_head as if it were a node where the value of p_node_before_head->p_next is the value of p_head
#include <iostream>

struct Node{
    Node* p_next;
    int item;   
};

int main(){
    Node head = {nullptr, 5};
    Node* p_head = &head;
    
    //By pretending that "p_head" is a node whose first element is a pointer to the head,
    //we create a new pointer that points to this "node before the head"
    Node* p_node_before_head = reinterpret_cast<Node*>(&p_head);
    
    Node* p_head2 = p_node_before_head->p_next;
    std::cout << p_head2->item << std::endl;
}

Is this reinterpret cast undefined behaviour? I am bit confused on how to determine whether casting a pointer of one type to a pointer of another type follows pointer-interconvertibility.


Solution

  • No that's undefined behavior. You can never pretend that an object of some type exists at some address where you never explicitly (or implicitly) created an object of such a type.

    At the address &p_head there is a Node* object, but no Node object. Therefore the result of the reinterpret_cast can't point to any Node object and consequently the member access p_node_before_head->p_next has undefined behavior.

    Pointer-interconvertibility doesn't even matter, because to begin with there is no Node object at the address in question. So there surely can't exist any Node object that is pointer-interconvertible with the Node* object either.

    In fact it is fundamentally impossible for a Node object to exist at the address in question, because the width of the storage at that address is too small for a Node object.