Understanding char *, char[] and strcpy()

CS Student picture CS Student · Aug 26, 2014 · Viewed 10.7k times · Source

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? */

Answer

unwind picture unwind · Aug 26, 2014

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'