Search code examples
cpointersinitializationlanguage-lawyerc23

Can you declare a C pointer with its own address?


Can I declare a C pointer with an intialization to its own address?

void* p = &p;

I am specifically concerned with if this is strictly standard compliant in C23 (as the draft currently stands).

I assume this question is equivalent to if the following works, which is closer to my actual use case:

typedef struct st {
   void* p;
   } st;

st x = { .p = &x };

Solution

  • It should be fine. I can't think of any part of the standard making this invalid and C23 didn't bring anything new that changed this either.

    The most relevant part of the standard would be 6.6 regarding address constants used as initializers (from the C23 draft N3096):

    An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly using an expression of array or function type.

    The array-subscript [] and member-access -> operator, the address & and indirection * unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.

    New in C23 is the following, mostly related to constexpr situations and compound literals:

    A structure or union constant is a named constant or compound literal constant with structure or union type, respectively.

    An implementation may accept other forms of constant expressions; however, they are not an integer constant expression.

    Starting from a structure or union constant, the member-access . operator may be used to form a named constant or compound literal constant as described above.
    If the member-access operator . accesses a member of a union constant, the accessed member shall be the same as the member that is initialized by the union constant’s initializer.

    From a practical point of view beyond the C standard, any variable we declare ought to already have a memory location before we initialize it, or otherwise how would the program know where to store that initializer? (Using the & operator also means it can't be stored in a register.) The C standard is purposely vague when it comes to where/how variables are stored in memory, so it won't cover things like linker addresses, stack offsets and the like.