#include<stdio.h>
int main()
{
char str[25] = "Hello World";
printf("%s\n", &str+2);
printf("%p\n",&str);
printf("%p\n",&str+2);
return 0;
}
The program above flashes an error for line 6 saying:
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[25]’ [-Wformat=]
I wonder what's the difference between these two. And the output always shows two addresses having a difference of 32 bytes. I was expecting an output with a difference of 2 as I'm trying to print the address of str
and address of str
+2. Can you explain?
The difference for this two cases is quite simple. Assume that we have an array of 25 characters: char arr[25];
. By convention expression arr
evaluated to a pointer to first array element, ie arr
is the same as &arr[0]
. Note, that here unary operator &
is applied to lvalue arr[0]
which has type of char
. And as result &
gives an expression with type char *
(ie pointer to char
)
When we say &arr
- the lvalue is arr
, that is char [25]
(ie array of 25 characters). And as result the whole expression has type char (*)[25]
(ie pointer to array of 25 characters). So, we've got expression with completely another type, that is not compatible with char *
.
Few notes about indexing. Difference between &arr + 2
and &arr
is 50 bytes (0x32 in hexadecimal), because sizeof(arr) == 25
.
char *
is a pointer to char
while char (*)[25]
is a pointer to an array of 25 char
's so these types are different and the compiler rightfully issues a warning.
Moreover, since &str
is the address of the str
array and is of type char (*)[25]
, the value of &str+2
will be equal to:
&str + 2*sizeof(char (*)[25]) = &str + 2*25 = &str + 50 = &str + 0x32
Since a pointer is incremented according to the type it points to.
EDIT: after OP added a new line 6.
This is the correct syntax to print a string and pointer values. In all cases there was a &
where it should not be, because a reference to the array identifier decays it to a pointer.
#include <stdio.h>
int main()
{
char str[25] = "Hello World";
printf("%s\n", str+2);
printf("%p\n", (void*)str);
printf("%p\n", (void*)(str+2));
return 0;
}
Program output:
llo World
0018FF20
0018FF22
EDIT 2: This shows the effect of passing the pointer of the array. The compiler thinks you are addressing the third element of an array of strings each size 25. I have contrived to show how this undefined behaviour actually manifested.
#include <stdio.h>
int main()
{
char str[25] = "Hello World";
char abc[] = "abcdefghijklmnopqrstuvwxyz";
printf("%s\n", &str+2);
return 0;
}
Program output:
wxyz
After a little research I came up with this explanation. &str+2
is treated as a pointer to an array. char (*)[25]
says that it's a pointer to a character array of size 25. To find the explain to why the output shows 32 byte difference I ran the program again and notices the output was displayed in hex ie
0x7ffd865b2710
0x7ffd865b2742
When converted to base 10, it becomes a difference of 50 bytes which is a pointer to the array that lies at second place to the current array(remember &str+2). TO make it more clear here's a little memory diagram.
&str -----> current array ie str. array is 25 bytes long.
&str+1 -----> array lies after 1 position to current array. This address is 25 bytes away from &str.
&str+2-----> array lies after 2 position to current array. This address is 50 bytes away from &str.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.