In C, "strings" are NUL-terminated arrays of characters.
The code char *s = "abcde";
does two things:
First, it allocates (in read-only program data) some (unnamed) memory, and populates it with "abcde"
:
1000 1001 1002 1003 1004 1005
_________________________________________
| a | b | c | d | e | \0 |
|______|______|______|______|______|______|
Then, in the stack frame of main
, a pointer to char
is allocated, named s
, and its value is initialized with the address of your string. In my example, s = 1000
.
1000 1001 1002 1003 1004 1005
_________________________________________
| a | b | c | d | e | \0 |
|______|______|______|______|______|______|
^
|
|
s = 1000
The %s
format specifier tells printf
to expect the address of a NUL-terminated string as the corresponding argument..
When you pass s
, you are doing just that: telling printf
that your string lives at address 1000. printf
goes to that address, and starts reading the characters there (a
, b
, c
...) until it encounters a NUL ('\0'
) character, at which point it stops. It has now read your string.
When you pass *s
, two things happen. First, the program de-references the pointer. Since it is a pointer-to-char, that means it reads one character from the memory at 1000. The result of this is 'a'
, which is the decimal number 97. Now, this value is passed to printf
(as before), and printf
still thinks it's an address. However, 97 is an invalid address, and your program crashes.
If you need to brush up on your understanding of pointers: