This question may seems quite duplicated; however, I indeed have had a serious survey on this site and still cannot quite understand.
char str[] = "test";
printf("%p\n", str);
printf("%p\n", &str);
I know str
itself is a pointer which points to the starting location that stores "t". Therefore I expect that printf("%p\n", str);
shows this address (say 000000FFE94FFC34
). Next, I wish to know in my OS, at what memory location that stores the exact information 000000FFE94FFC34
. (i.e. the address of str
itself.)
However, the output of the third line is the same as the previous one. It seems quite a weird behavior. And how can I figure out the address of str
itself? I guess this can be achieved by using another new pointer that points to the pointer I want, i.e. char **super_pointer = str;
but I think it is an unnecessarily complicated way.
CodePudding user response:
Lets draw it out with the pointers added, to hopefully make it simpler to understand:
-------- -------- -------- -------- -------- | str[0] | str[1] | str[2] | str[3] | str[4] | -------- -------- -------- -------- -------- ^ | &str[0] | &str
As you can see the pointer to the first element (&str[0]
which is what plain str
decays to) points to the same location as the array itself (&str
).
But (and it's an important but): The type are very different!
The type of &str[0]
is char *
.
The type of &str
is char (*)[5]
.
On another note you say that
...
str
itself is a pointer...
This is wrong. str
itself is the array, which can decay to a pointer to its first element.
CodePudding user response:
I know str itself is a pointer which points to the starting location that stores "t".
As you wrote "str itself" is not a pointer it is an array. But used in expressions array designators with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
In this call
printf("%p\n", str);
the array designator str
used as an argument expression is converted to a pointer to its first element. In fact this call is equivalent to
printf("%p\n", &str[0]);
That is this call output the starting address of the extent of memory occupied by the array.
This call
printf("%p\n", &str);
that is better to write as and the previous call like
printf("%p\n", ( void * )&str);
also outputs the starting address of the extent of memory occupied by the array.
What is the difference?
The expression str
used in the call of printf
has the type char *
while the expression &str
has the type char ( * )[5]
.
The both expressions is interpreted by the call as expressions of the type void *
.
To make this more clear consider a two dimensional array
char str[2][6] = { "test1", "test2" };
The addresses of the array as whole and of its first "row" and of its first character of the first "row" are coincide.
That is the expression &sgtr
that has the type char ( * )[2][6]
and the expression &str[0]
that has the type char ( * )[6]
and the expression &str[0][0]
that has the type char *
yield the same value: hhe starting address of the extent of memory occupied by the array..