This code produces \"p = hello world\":
#include \"stdio.h\"
#include \"string.h\"
int main(){
char *p;
p=\"hello world\";
printf(\"p is %s \\n\",p)
There is no free lunch - you need to grab & manage memory. If you just assume that because you have access to a pointer memory should be there then you'll run into unspecified behavior (segfault likely).
The reason is that when you declare a pointer, it doesn't actually point to anything useful. strcpy
requires a block of memory for the string to be copied into. It will not do this for you automatically.
From the documentation (emphasis mine):
Copies the C string pointed by source into the array pointed by destination, including the terminating null character.
To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.
You need to make this true, as it is a precondition of the function.
Also, in the parameters section:
destination
Pointer to the destination array where the content is to be copied.
You need to make sure destination
is a pointer to an array.
Notice what the two working examples have in common: they have a p =
line that assigns something to p
. The non-working example does not do this.
Consider this line (from the first example):
p = "hello world";
Although it might look like it's "copying a string to a char pointer", it's not. It's copying the location of a string to a pointer-to-char. That's what a pointer-to-char like p
stores - the location of a contiguous block of char
s.
Similarly, consider this line from the third example:
p = malloc(10);
This is also copying a location - it's copying the location of a block of 10 unintialised char
s into p
.
strcpy(dest, source)
copies characters from the location given by source
to the location given by dest
. It should be clear that if you never set p
to a valid location, then strcpy(p, "hello")
can't do anything sensible - in your second example, p
is an essentially random location, and you then ask strcpy()
to copy something to that location.
Yes its annoying. You can use strdup
to shorten it:
char *p = strdup("hello");
printf("p is %s \n",p);
In the case where p="hello world";
(1st case at the time of this edit), p
is being initialized to point to a read-only memory region which contains the string "hello world" (string literal). This read-only memory region is created at compile time.
In the case that causes the segmentation fault (2nd case at the time of this edit), p
is uninitialized and copying anything to it will produce unpredictable results because the location in memory that p
is pointing to is not specified by the code.
Before you can copy a string to p
, you must specify the memory that p
is pointing to.
You can allocate this memory on the stack
char buf[BUFSIZ] = ""; /* local variable */
on the heap
char *buf = malloc(BUFSIZ); /* don't forget to free */
or in the __DATA segment.
static char buf[BUFSIZ] = ""; /* global variable */
You can then initialize p
to point at the memory buffer.
char *p = buf;
This is similar in concept to initializing p
to point to the string literal in read-only memory. Unlike the case where p
points to the string literal, you can now copy a string to the character pointer as it does not point to read-only memory.
Note: I intentionally created a separate buffer and initialized p
to point to it to help make my point.
There are two distinct parts to memory copying. The first is the memory occupied by the item you want to copy (which you create in your example using the malloc() function), and the second is a pointer to that block of memory (which you call p). These two entities must be set up for the destination too, before you can do a copy. In your first example that fails, you have not set up the memory block for the destination (but it has been set for the source implicitly when you declare the string hello
).