问题
Can somebody clealry explain me the concept behind multiple reference and dereference ? why does the following program gives output as 'h' ?
int main()
{
char *ptr = "hello";
printf("%c\n", *&*&*ptr);
getchar();
return 0;
}
and not this , instead it produces 'd' ?
int main()
{
char *ptr = "hello";
printf("%c\n", *&*&ptr);
getchar();
return 0;
}
I read that consecutive use of '*' and '&' cancels each other but this explanation does not provide the reason behind two different outputs generated in above codes?
回答1:
The first program produces h
because &
s and *
s "cancel" each other: "dereferencing an address of X" gives back the X:
ptr
- a pointer to the initial character of"hello"
literal*ptr
- dereference of a pointer to the initial character, i.e. the initial character&*ptr
the address of the dereference of a pointer to the initial character, i.e. a pointer to the initial character, i.e.ptr
itself
And so on. As you can see, a pair *&
brings you back to where you have started, so you can eliminate all such pairs from your dereference / take address expressions. Therefore, your first program's printf
is equivalent to
printf("%c\n", *ptr);
The second program has undefined behavior, because a pointer is being passed to printf
with the format specifier of %c
. If you pass the same expression to %s
, the word hello
would be printed:
printf("%s\n", *&*&ptr);
回答2:
Lets go through the important parts of the program:
char *ptr = "hello";
makes a pointer to char
which points to the string literal "hello"
. Now, for the confusing part:
printf("%c\n", *&*&*ptr);
Here, %c
expects a char
. Let us look into what type *&*&*ptr
is. ptr
is a char*
. Applying the dereference operator(*
) gives a char
. Applying the address-of operator to this char
gives back the char*
. This is repeated again, and finally, the *
at the end gives us a char
, the first character of the string literal "hello"
, which gets printed.
In the second program, in
*&*&ptr
, you first apply the &
operator, which gives a char**
. Applying *
on this gives back the char*
. This is repeated again and finally , we get a char*
. But %c
expects a char
, not a char*
. So, the second program exhibits Undefined Behavior as per the C11 standard (emphasis mine):
7.21.6.1 The fprintf function
[...]
- If a conversion specification is invalid, the behavior is undefined.282If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
So, basically, anything can happen when you execute the second program. Your program might crash, emit a segmentation-fault, output weird things, or do something else.
BTW, you are right about saying:
I read that consecutive use of '*' and '&' cancels each other
回答3:
Let's break down what *&*&*ptr
actually is, but first, remember that when applying *
to a pointer, it gives you what that pointer points to. On the other hand, when applying &
to a variable, it gives you the address in memory for that variable.
Now, after getting a steady ground, let's see what you have here:
ptr
is a pointer to a char
, thus when doing *ptr
it gives you the data which ptr
points to, in this case, ptr
points to a string "hello"
, however, a char
can hold only one char, not a whole string, right? so, it point to the beginning of such a string, which is the first character in it, aka h
.
Moving on...*&*&*ptr=*&*&(*ptr) = *&*&('h')= *&*(&'h') = *&*(ptr)=*&(*ptr) = *&('h')= *ptr = 'h'
If you apply the same pattern on the next function, I'm pretty sure you can figure it out.
SUMMARY: read pointers from the right to the left!
来源:https://stackoverflow.com/questions/30423589/multiple-reference-and-dereference-in-c