10

Attempting to modify a string literal causes undefined behavior:

char * p = "wikipedia"; 
p[0] = 'W'; // undefined behaviour

One way to prevent this is defining it as an array instead of a pointer:

char p[] = "wikipedia"; 
p[0] = 'W'; // ok

Why does char* cause undefined behaviour, while char[] doesn't?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Terry Li
  • 16,870
  • 30
  • 89
  • 134

1 Answers1

16

Any attempt to modify a C string literal has undefined behaviour. A compiler may arrange for string literals to be stored in read-only memory (protected by the OS, not literally ROM unless you're on an embedded system). But the language doesn't require this; it's up to you as a programmer to get it right.

A sufficiently clever compiler could have warned you that you should have declared the pointer as:

const char * p = "wikimedia";

though the declaration without the const is legal in C (for the sake of not breaking old code). But with or without a compiler warning, the const is a very good idea.

(In C++, the rules are different; C++ string literals, unlike C string literals, really are const.)

When you initialize an array with a literal, the literal itself still exists in a potentially read-only region of your program image, but it is copied into the local array:

char s[] = "wikimedia"; /* initializes the array with the bytes from the string */
char t[] = { 'w', 'i', ... 'a', 0 };  /* same thing */

Note that char u[] = *p does not work -- arrays can only be initialized from a brace initializer, and char arrays additionally from a string literal.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Any self-respecting programmer would have considered the const-correctness ;) ... +1 – 0xC0000022L Nov 28 '11 at 21:11
  • The question is tagged `C`. In `C`, the type of `"foo"` is array of char. I do not see on what basis the compiler should warn that you should have declared the pointer as ... – Pascal Cuoq Nov 28 '11 at 21:14
  • @Complicatedseebio: On basis that you're not allowed to mutate the contents :-) (That's what *warnings* are for.) – Kerrek SB Nov 28 '11 at 21:15
  • +1 very helpful for c++ newbies like me. I would never know I'd better precede char* with const otherwise. Thanks. – Terry Li Nov 28 '11 at 21:16
  • Nevertheless, you are allowed to assign "foo" to a `char *` variable. Any warning there would be quite unwelcome. – Pascal Cuoq Nov 28 '11 at 21:17
  • @Complicatedseebio: Yes, it's allowed, and thus it's not an error. But it's something worth warning about. Like `if (n = 0)`. – Kerrek SB Nov 28 '11 at 21:21
  • No, the C standard definitely does *not* say that string literals are stored in read-only memory. It merely says that the behavior of attempting to modify the array corresponding to a string literal is undefined. The array is not `const`. A warning is reasonable, but is not required. – Keith Thompson Nov 30 '11 at 16:18