I have heard many people saying that in C *
and &
actually nullify the effects of each other, in situations wherever they are valid.
Suppose just for illustration I define and initialize a pointer as follows:
int *ptr=2000;
Clearly the value which I assigned to ptr
is arbitrary and trying to deference it might possibly cause segmentation fault. I do not exactly remember the entire code, but I once read a data structure book where the author was showing some calculations on structural padding. I guess there was statements which roughly meant something like this:
int *newptr=&*ptr;
Like those many people I felt that &
and *
cancelled each other and we have newptr
assigned the value of ptr
namely 2000
in the above example.
The statement that &
and *
cancel each other is not always true. Take the case of an integer variable. And if we apply somethings as:
int x=10;
int y=&*x;
The compiler quite naturally puts forth an error saying invalid type argument of unary ‘*’ (have ‘int’)
. This is quite clear from the way C tries to parse the expression &*x
. Which is like (&(*x))
Now coming back to the actual question, C should parse the expression &*ptr
as (&(*ptr))
. So what I feel is that first *ptr
should be calculated and then address of it should be taken. But this brings up a possibility of segmentation fault
while trying to do *ptr
first, given that ptr
contains some garbage.
I tried quite many times the same thing, by randomly assigning a value to ptr
by a random number generator and then applying &*ptr
. But luckily none of the times there was any segmentation fault.
May be I was very lucky. But given the situation I feel that it is quite unlikely that I am getting lucky each and everytime and possibly C compiler is doing something smart contrary to what I have thought. Probably on just seeing &* applied to a pointer, it just uses the raw value of the pointer instead of just going into the headache of first (*ptr) and then taking & of the result.
But the thing is that, I am unable to figure out as to what is the situation actually. Please can anyone help me out?
CodePudding user response:
The pointer is not actually dereferenced, so there is no UB.
C11 — 6.5.3.2 Address and indirection operators
3 — ... If the operand is the result of a unary
*
operator, neither that operator nor the&
operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.
Now, you might be wondering if the pointer being valid is a part of the "constraints". Apparently not, because right above that there's following section:
Constraints
1 — The operand of the unary
&
operator shall be either a function designator, the result of a[]
or unary*
operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.2 — The operand of the unary
*
operator shall have pointer type.