Understanding char *, char [] and strcpy ()
My understanding is this:
-
char *
points to a string constant, changing the data it points to is undefined. However, you can change what it points to. -
char[]
refers to a block of memory that you can change its contents, but not what it refers to. -
strcpy(dest, src)
copiessrc
todest
.
My question is, is it wrong to use strcpy()
when dest
is char *
, which already points to something (since I believe old content will be overwritten strcpy()
- this is undefined behavior)?
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? */
source to share
Unfortunately, your understanding is not entirely correct.
char *
points to character data, and since there isn't const
, you can write to the data it points to.
However, this is quite possible:
char *a = "hello";
which gives you a read / write pointer to read-only data, since string literals are stored in permanent memory, but are not "considered" constants by the language syntax.
Better to write above:
const char *a = "hello";
To make it clearer, you cannot change the data it points to a
.
Also, your mix malloc()
and assignment examples are wrong.
It:
char *dest = malloc(5);
dest = "FIVE"; /* BAD CODE */
Bad code and you should never do that. It just overwrites the pointer returned by a dest
pointer to a string "FIVE"
that exists somewhere (again, read-only) as a string literal.
The correct way to initialize 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 malloc()
is a good idea.
There is no problem doing multiple writes to the same memory, which is a very simple idea in C; variables are memory and can be assigned different values ββat different times, being "overwritten".
Something simple:
int a = 2;
printf("a=%d\n", a);
a = 4;
printf("a=%d\n", a);
demonstrates this, and it works great for strings too, of course, since they are just blocks of memory.
You can expand on the above example malloc()
:
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'
source to share
My understanding is this:
char *
points to a string constant, changing the data it points to is undefined. However, you can change what it points to.
Here you are referring to an expression like
char * string = "mystring";
You are correct that the execution string[1]='r';
is undefined. But this is not because of char *
, but because of the string literal associated with the fact that it is placed in permanent memory.
Compare this with
char string[] = "mystring";
where I define an array in RAM where the specified string fits. It is allowed to do here string[1] = 'r';
because we are in normal data memory.
This looks like your guess, but take this:
char string[] = "mystring";
char * string2 = string;
string2[1] = 'r';
Valid here as it points to a place where the entry is also good.
char[] refers to a block of memory that you can change its contents but not what it refers to.
Yes, because the name there is just a variable name, not a pointer.
strcpy(dest, src) copies src into dest.
Right.
My question is, is it wrong to use strcpy () when dest is a char * that already points to something (as I believe the content will be overwritten by strcpy () - which is undefined behavior)?
It depends on what you mean by "already pointing to something" ...
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? * /
Here you are mixing a few things again.
First, you have it dest
pointed to a new block of memory. After that, you point to the place where you cannot write and the chunk of memory is lost (memory leak).
The same thing happens with src
.
So, it strcpy()
fails.
You can do
char *dest = malloc(5);
char *src = "NEW!";
strcpy(dest, src);
as here dest
indicates the place to be written, but src
indicates the payload.
source to share
Quick analysis:
char *dest = malloc(5);
// 'dest' is set to point to a piece of allocated memory
// (typically located in the heap)
dest = "FIVE";
// 'dest' is set to point to a constant string
// (typically located in the code-section or in the data-section)
You are assigning to the variable dest
twice, so obviously the first assignment doesn't matter.
I like to write:
int i = 5; i = 6;
In addition, you "lose" the address of the allocated memory, so you cannot release it later.
source to share
char * is a pointer to a memory address, so you can change the information contained in that address.
The difference between char * and char [] is that char [] is not dynamic, you cannot resize it. Also, char * points to a heap address, while char [] is stored on the stack of your program.
You can use strcpy with both pointers and arrays and it will work as data from both can be overwritten.
source to share