I am trying to understand pointers in C but I am currently confused with the following:
char *p = "hello"
This is a char pointer pointing at the character array, starting at h.
char p[] = "hello"
This is an array that stores hello.
What is the difference when I pass both these variables into this function?
void printSomething(char *p)
{
printf("p: %s",p);
}
You're not allowed to change the contents of a string constant, which is what the first
p
points to. The secondp
is an array initialized with a string constant, and you can change its contents.Let's see:
foo* and foo[] are different types and they are handled differently by the compiler (pointer = address + representation of the pointer's type, array = pointer + optional length of the array, if known, for example, if the array is statically allocated), the details can be found in the standard. And at the level of runtime no difference between them (in assembler, well, almost, see below).
Also, there is a related question in the C FAQ:
char*
andchar[]
are different types, but it's not immediately apparent in all cases. This is because arrays decay into pointers, meaning that if an expression of typechar[]
is provided where one of typechar*
is expected, the compiler automatically converts the array into a pointer to its first element.Your example function
printSomething
expects a pointer, so if you try to pass an array to it like this:The compiler pretends that you wrote this:
char p[3] = "hello"
? should bechar p[6] = "hello"
remember there is a '\0' char in the end of a "string" in C.anyway, array in C is just a pointer to the first object of an adjust objects in the memory. the only different s are in semantics. while you can change the value of a pointer to point to a different location in the memory an array, after created, will always point to the same location.
also when using array the "new" and "delete" is automatically done for you.
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:
As far as I can remember, an array is actually a group of pointers. For example
is a true statement