My understanding is as follows:
char *
points to a string constant, modifying the data it points to is undefined. You can, however, change where it points to.
char[]
refers to a block of memory that you can change. You can change its contents but not what it refers to.
strcpy(dest, src)
copies src
into dest
.
My question is, is it incorrect to use strcpy()
with the dest
being a char *
that is already pointing to something (as I believe the old contents will be overwritten by strcpy()
- which is undefined behaviour)?
For example:
char *dest = malloc(5);
dest = "FIVE";
char *src = malloc(5);
src = "NEW!";
strcpy(dest, src); /* Invalid because chars at dest are getting overwritten? */
Your understanding is not totally correct, unfortunately.
char *
points at character data, and since there's no const
in there, you can write to the data being pointed to.
However, it's perfectly possible to do this:
char *a = "hello";
which gives you a read/write pointer to read-only data, since string literals are stored in read-only memory, but not "considered" constant by the language's syntax.
It's better to write the above as:
const char *a = "hello";
To make it more clear that you cannot modify the data pointed at by a
.
Also, your examples mixing malloc()
and assignment are wrong.
This:
char *dest = malloc(5);
dest = "FIVE"; /* BAD CODE */
Is bad code, and you should never do that. It simply overwrites the pointer returned by dest
with a pointer to the string "FIVE"
which exists somewhere in (again, read-only) memory as a string literal.
The proper way to initalize newly allocated memory with string data is to use strcpy()
:
char *dest = malloc(5);
if(dest != NULL)
strcpy(dest, "five");
Note that checking the return value of malloc()
is a good idea.
There's no problem doing multiple writes to the same memory, that's a very basic idea in C; variables represent memory, and can be given different values at different times by being "written over".
Something as simple as:
int a = 2;
printf("a=%d\n", a);
a = 4;
printf("a=%d\n", a);
demonstrates this, and it works just fine for strings too of course since they are just blocks of memory.
You can extend the above malloc()
-based example:
char *dest = malloc(5);
if(dest != NULL)
{
strcpy(dest, "five");
printf("dest='%s'\n", dest);
strcpy(dest, "four");
printf("dest='%s'\n", dest);
strcpy(dest, "one");
printf("dest='%s'\n", dest);
}
and it will print:
dest='five'
dest='four'
dest='one'