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);
return 0;
}
But this code produces a segmentation fault:
#include "stdio.h"
#include "string.h"
int main() {
char *p;
strcpy(p,"hello");
printf("p is %s \n",p);
return 0;
}
and this code produces "p = hello"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main() {
char *p;
p=(char*)malloc (10);
strcpy(p,"hello");
printf("p is %s \n",p);
return 0;
}
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):
You need to make this true, as it is a precondition of the function.
Also, in the parameters section:
You need to make sure
destination
is a pointer to an array.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
).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 thatp
is pointing to is not specified by the code.Before you can copy a string to
p
, you must specify the memory thatp
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 wherep
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.Notice what the two working examples have in common: they have a
p =
line that assigns something top
. The non-working example does not do this.Consider this line (from the first example):
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 ofchar
s.Similarly, consider this line from the third example:
This is also copying a location - it's copying the location of a block of 10 unintialised
char
s intop
.strcpy(dest, source)
copies characters from the location given bysource
to the location given bydest
. It should be clear that if you never setp
to a valid location, thenstrcpy(p, "hello")
can't do anything sensible - in your second example,p
is an essentially random location, and you then askstrcpy()
to copy something to that location.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).
Yes its annoying. You can use
strdup
to shorten it: