This question already has an answer here:
Consider:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
I read from The C Programming Language, 2nd Edition that the above two statements don't do the same thing.
I always thought that an array is an convenient way to manipulate pointers to store some data, but this is clearly not the case... What are the "non-trivial" differences between arrays and pointers in C?
I can't add usefully to the other answers, but I will remark that in Deep C Secrets, Peter van der Linden covers this example in detail. If you are asking these kinds of questions I think you will love this book.
P.S. You can assign a new value to
pmessage
. You can't assign a new value toamessage
; it is immutable.The first form (
amessage
) defines a variable (an array) which contains a copy of the string"now is the time"
.The second form (
pmessage
) defines a variable (a pointer) that lives in a different location than any copy of the string"now is the time"
.Try this program out:
You'll see that while
&amessage
is equal to&amessage[0]
, this is not true for&pmessage
and&pmessage[0]
. In fact, you'll see that the string stored inamessage
lives on the stack, while the string pointed at bypmessage
lives elsewhere.The last printf shows the address of the string literal. If your compiler does "string pooling" then there will be only one copy of the string "now is the time" -- and you'll see that its address is not the same as the address of
amessage
. This is becauseamessage
gets a copy of the string when it is initialized.In the end, the point is that
amessage
stores the string in its own memory (on the stack, in this example), whilepmessage
points to the string which is stored elsewhere.The second one allocates the string in some read-only section of the ELF. Try the following:
and you will get a segfault on the second assignment (pmessage[3]='S').
True, but it's a subtle difference. Essentially, the former:
Defines an array whose members live in the current scope's stack space, whereas:
Defines a pointer that lives in the current scope's stack space, but that references memory elsewhere (in this one, "now is the time" is stored elsewhere in memory, commonly a string table).
Also, note that because the data belonging to the second definition (the explicit pointer) is not stored in the current scope's stack space, it is unspecified exactly where it will be stored and should not be modified.
Edit: As pointed out by Mark, GMan, and Pavel, there is also a difference when the address-of operator is used on either of these variables. For instance, &pmessage returns a pointer of type char**, or a pointer to a pointer to chars, whereas &amessage returns a pointer of type char(*)[16], or a pointer to an array of 16 chars (which, like a char**, needs to be dereferenced twice as litb points out).
Here's a hypothetical memory map, showing the results of the two declarations:
The string literal "now is the time" is stored as a 16-element array of char at memory address 0x00008000. This memory may not be writable; it's best to assume that it's not. You should never attempt to modify the contents of a string literal.
The declaration
allocates a 16-element array of char at memory address 0x00500000 and copies the contents of the string literal to it. This memory is writable; you can change the contents of amessage to your heart's content:
The declaration
allocates a single pointer to char at memory address 0x00500010 and copies the address of the string literal to it.
Since pmessage points to the string literal, it should not be used as an argument to functions that need to modify the string contents:
and so on. If you changed pmessage to point to amessage:
then it can be used everywhere amessage can be used.
A pointer is just a variable that holds a memory address. Notice that you are playinf with "string literals" which is another issue. Differences explained inline: Basically: