0

Define the following variables:

char *name1 = "Allan";
char name2[] = "Marco";
printf("%s %s\n", name1, name2); // Allan Marco

Then the following code works fine:

strcpy(name2, name1);
printf("%s %s\n", name1, name2); // Allan Allan

But reversing the arguments corrupts the string:

strcpy(name1, name2);
printf("%s %s\n", name1, name2); // Does not work!

Why does this not work? name1 and name2 both evaluate to pointers to the first element of their respective strings, so why does strcpy discriminate between the two variables? And furthermore, why does it not work?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Ivan
  • 1
  • With `char name2[] = "Marco";`, name2 is only guaranteed to be at least large enough to hold the string "Marco" (6 chars). If you try to write more data than will fit, the behavior is undefined. Perhaps try: `char name2[128] = "Marco";` to give yourself more space. – William Pursell Jan 18 '22 at 14:49
  • With `char *name1 = "Allan"`, name1 points to memory that may be read only, so you cannot modify the contents. – William Pursell Jan 18 '22 at 14:51
  • Please see this C string beginner FAQ: [Common string handling pitfalls in C programming](https://software.codidact.com/posts/284849) Basically you have to allocate memory to store the strings in. – Lundin Jan 18 '22 at 15:20

2 Answers2

1

In this call

strcpy(name1, name2);

you are trying to change the string literal pointed to by the pointer name1.

char *name1 = "Allan";

Any attempt to change a string literal results in undefined behavior.

From the C Standard (6.4.5 String literals)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

As for this call

strcpy(name2, name1);

then there are overwritten elements of a character array declared like

char name2[] = "Marco";
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Why are there overwritten elements in the second case? – Ivan Jan 18 '22 at 14:51
  • @Ivan because `name2` is only large enough to hold 6 characters. You can write to `name2[5]`, but an attempt to write to `name2[6]` is undefined behavior. – William Pursell Jan 18 '22 at 14:52
  • @Ivan The array was initialized by the string "Marco" and the call of strcpy strcpy(name2, name1); overwrites elements of the array with elements of the string literal pointed to by the pointer nameq. – Vlad from Moscow Jan 18 '22 at 14:53
  • @WilliamPursell But isn't name1, the string literal "Allan", also at most 6 characters? – Ivan Jan 18 '22 at 14:55
  • @Ivan Saying overwrites elements I mean changes elements. Now elements of the array contain new values. – Vlad from Moscow Jan 18 '22 at 14:57
  • @Ivan Indeed (I thought this was `strcat`!). But you say that this case works fine for you, so I'm not sure what the concern is. – William Pursell Jan 18 '22 at 14:59
  • Depending on the system, a string literal may even be stored in non-writable memory (e.g. flash or eeprom). – nielsen Jan 18 '22 at 15:04
0

All literal strings in C are really null-terminated char arrays, and your pointer name1 is pointing to the first element of such an array.

The problem is that the array of a literal string is not allowed to be modified, it's essentially read-only. Attempting to modify a literal string leads to undefined behavior.

That's why it's recommended to use const char * to point to literal strings.


Another important note: The variable name2 is not a pointer, it's an actual array. It can decay to a pointer (to its first element).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621