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?
For this line: char amessage[] = "now is the time";
the compiler will evaluate uses of amessage as a pointer to the start of the array holding the characters "now is the time". The compiler allocates memory for "now is the time" and initializes it with the string "now is the time". You know where that message is stored because amessage always refers to the start of that message. amessage may not be given a new value- it is not a variable, it is the name of the string "now is the time".
This line: char *pmessage = "now is the time";
declares a variable, pmessage which is initialized (given an initial value) of the starting address of the string "now is the time". Unlike amessage, pmessage can be given a new value. In this case, as in the previous case, the compiler also stores "now is the time" elsewhere in memory. For example, this will cause pmessage to point to the 'i' which begins "is the time". pmessage = pmessage + 4;
If an array is defined so that its size is available at declaration time,
sizeof(p)/sizeof(type-of-array)
will return the number of elements in the array.C99 N1256 draft
There are two different uses of character string literals:
Initialize
char[]
:This is "more magic", and described at 6.7.8/14 "Initialization":
So this is just a shortcut for:
Like any other regular array,
c
can be modified.Everywhere else: it generates an:
So when you write:
This is similar to:
Note the implicit cast from
char[]
tochar *
, which is always legal.Then if you modify
c[0]
, you also modify__unnamed
, which is UB.This is documented at 6.4.5 "String literals":
6.7.8/32 "Initialization" gives a direct example:
GCC 4.8 x86-64 ELF implementation
Program:
Compile and decompile:
Output contains:
Conclusion: GCC stores
char*
it in.rodata
section, not in.text
.If we do the same for
char[]
:we obtain:
so it gets stored in the stack (relative to
%rbp
).Note however that the default linker script puts
.rodata
and.text
in the same segment, which has execute but no write permission. This can be observed with:which contains:
Along with the memory for the string "now is the time" being allocated in two different places, you should also keep in mind that the array name acts as a pointer value as opposed to a pointer variable which pmessage is. The main difference being that the pointer variable can be modified to point somewhere else and the array cannot.
Here is my summary of key differences between arrays and pointers, which I made for myself:
An array contains the elements. A pointer points to them.
The first is a short form of saying
That is, it is an array that contains all the characters. The special initialization initializes it for you, and determines it size automatically. The array elements are modifiable - you may overwrite characters in it.
The second form is a pointer, that just points to the characters. It stores the characters not directly. Since the array is a string literal, you cannot take the pointer and write to where it points
This code would probably crash on your box. But it may do anything it likes, because its behavior is undefined.