Expanding on Christian Gibbons' answer a bit...
In C, string literals, like "Hello, World!"
, are stored in arrays of char
such that they are visible over the lifetime of the program. String literals are supposed to be immutable, and some implementations will store them in a read-only memory segment (such that attempting to modify the literal's contents will trigger a runtime error). Some implementations don't, and attempting to modify the literal's contents may not trigger a runtime error (it may even appear to work as intended). The C language definition leaves the behavior "undefined" so that the compiler is free to handle the situation however it sees fit.
In C++, string literals are stored in arrays of const char
, so that any attempt to modify the literal's contents will trigger a diagnostic at compile time.
As Christian points out, the const
keyword was not originally a part of C. It was, however, originally part of C++, and it makes using string literals a little safer.
Remember that the const
keyword does not mean "store this in read-only memory", it only means "this thing may not be the target of an assignment."
Also remember that, unless it is the operand of the sizeof
or unary *
operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
" and the value of the expression will be the address of the first element of the array.
In C++, when you write
const char *str = "Hello, world";
the address of the first character of the string is stored to str
. You can set str
to point to a different string literal:
str = "Goodbye cruel world";
but what you cannot do is modify the contents of the string, something like
str[0] = 'h';
or
strcpy( str, "Something else" );
Best Answer
Up through C++03, your first example was valid, but used a deprecated implicit conversion--a string literal should be treated as being of type
char const *
, since you can't modify its contents (without causing undefined behavior).As of C++11, the implicit conversion that had been deprecated was officially removed, so code that depends on it (like your first example) should no longer compile.
You've noted one way to allow the code to compile: although the implicit conversion has been removed, an explicit conversion still works, so you can add a cast. I would not, however, consider this "fixing" the code.
Truly fixing the code requires changing the type of the pointer to the correct type:
As to why it was allowed in C++ (and still is in C): simply because there's a lot of existing code that depends on that implicit conversion, and breaking that code (at least without some official warning) apparently seemed to the standard committees like a bad idea.