This answer is for the C-tag.
The expression:
void* x = &x;
is an init-declarator which is declarator = initializer
This can be found in section 6.7 of N1570 (draft C standard) and 6.7.6 says:
A full declarator is a declarator that is not part of another declarator. The end of a full
declarator is a sequence point.
And 6.2.1/7 says:
Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag. ...<some text not quoted>... Any other identifier has scope that begins just after the completion of its declarator.
These sections tell that the object is created before it is initialized. Consequently, the initializer can use the address of the created objected.
In section 6.3.2.3 Pointers:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Therefore - since any pointer can be converted to a void-pointer - the address of x
can be assigned to a void-pointer.
So for your code:
First the object is created and then it is initialized.
void* x = &x;
^^^^^^^ ^^^^^
| |
| step 2: initialize object
|
step 1: create object, i.e. end of full declarator
For this code it's pretty much the same as an assignment.
void* x; // Create
x = &x; // Assignment instead of initialization
// But in this case it works just the same