Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do string literals (char*) in C++ have to be constants?

I've recently been learning C++ and have realised that string literals in C++ have to be constants, whereas in C, they do not. Here is an example. The following code would be valid in C, but not in C++:

char* str = "Hello, World!";

In order to do the same thing in C++, the following statement has to be used:

const char* str = "Hello, World!";

Why is there a difference?

like image 622
Serket Avatar asked May 04 '20 21:05

Serket


People also ask

Are string literals constant in C?

TL;DR: In C, literals (of which there are only string literals) are lvalues; we can take their address. All other “literals” (numbers, characters) are constants in C; this means they are rvalues and we cannot take their address. In languages other than C, I tend to use “constant” and “literal” interchangeably.

Is char * A string literal?

String literals are convertible and assignable to non-const char* or wchar_t* in order to be compatible with C, where string literals are of types char[N] and wchar_t[N]. Such implicit conversion is deprecated.

Are string literals constant?

String constants, also known as string literals, are a special type of constants which store fixed sequences of characters. A string literal is a sequence of any number of characters surrounded by double quotes: "This is a string."

What is the difference between character constant and string literals?

Character Constants are written by enclosing a character within a pair of single quotes. String Constants are written by enclosing a set of characters within a pair of double quotes. Character Constants are assigned to variables of type char. String Constants are assigned to variables of type String.


Video Answer


2 Answers

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" );
like image 185
John Bode Avatar answered Oct 17 '22 06:10

John Bode


C didn't initially have the const keyword, so it would break legacy code if they changed literals to require const-qualification after introduction of the keyword. C's string-literals are immutable, though, so changing the contents is undefined behavior even if it's not const-qualified.

C++, on the other hand, was designed with the const keyword. Initially, C++ did allow for string literals to be assigned to non const-qualified char *s presumably for compatibility with existing C code. As of the C++03 standard, however, they decided to deprecate this functionality rather than allowing the dissonance to continue into perpetuity. I would guess the amount of legacy C++ code relying on non-const qualified char *s pointing to string literals to be small enough that it was a worthy trade-off.

like image 23
Christian Gibbons Avatar answered Oct 17 '22 05:10

Christian Gibbons