Is it bad to declare a C-style string without const? If so, why?
C++CC StringsC++ Problem Overview
Doing this in C++
char* cool = "cool";
compiles fine, but gives me a warning: > deprecated conversion from string constant to char.*
I would never willfully use a C-style string over std::string
, but just in case I'm asked this question:
is it bad practice to declare a C-style string without the const
modifier? If so, why?
C++ Solutions
Solution 1 - C++
Yes, this declaration is bad practice, because it allows many ways of accidentally provoking Undefined Behavior by writing to a string literal, including:
cool[0] = 'k';
strcpy(cool, "oops");
On the other hand, this is perfectly fine, since it allocates a non-const array of chars:
char cool[] = "cool";
Solution 2 - C++
Yes, in C++ you should always refer to string literals with variables of type const char *
or const char [N]
. This is also best practice when writing new C code.
String literals are stored in read-only memory, when this is possible; their type is properly const
-qualified. C, but not C++, includes a backward compatibility wart where the compiler gives them the type char [N]
even though they are stored in read-only memory. This is because string literals are older than the const
qualifier. const
was invented in the run-up to what's now called "C89" -- the earlier "K&R" form of the language did not have it.
Some C compilers include an optional mode in which the backward compatibility wart is disabled, and char *foo = "...";
will get you the same or a similar diagnostic that it does in C++. GCC spells this mode -Wwrite-strings
. I highly recommend it for new code; however, turning it on for old code is liable to require an enormous amount of scutwork for very little benefit.
Solution 3 - C++
It's bad. It's very bad. To the point this isn't possible to do anymore in C++11.
Modifying the memory of a string literal is undefined behaviour.
Solution 4 - C++
First, char* cool = "cool";
is not standard C++. A string literal has the type of const char[n]
. So the above line of code breaks const-correctness and should not compile. Some compilers like GCC allow this but issue a warning as it is a hold over from C. MSVC will issue a error since it is a error.
Second, why not let the compiler work for you? If it is marked const
then you will get a nice compiler error if you accidentally try to modify it. If you do not then you can get a really nasty run time error which can be much harder to find.
Solution 5 - C++
It is bad because string constants might be contained only once per binary (keyword: stringtable, .strtab
). E.g. in
char *cool = "cool";
char *nothot = "cool";
both variables can point to the same memory location. Modifying the contents of one of them might alter the other too, so that after
strcpy(nothot, "warm");
your cool
becomes "warm".
In short, it is undefined behaviour.
Solution 6 - C++
It is a string literal, therefore it should be constant as memory might be located in read only section. If you have char cool[] = "cool";
then it's not a problem, the memory is yours.
Solution 7 - C++
>char* cool = "cool"
"cool" will be stored in a read only block (generally in data segment) that is shared among functions. If you try to modify the string "cool" by the point cool you will get a error such as segment error when the program is running. If you use const char* cool = "cool"
, you will get a error when compile if you try to modify the string.
You can read this page for more information http://www.geeksforgeeks.org/storage-for-strings-in-c/
Solution 8 - C++
Its a good practice to write const for strings(especially when you used a string literal) but in C it hardly makes a difference ,it will throw you a warning in c++ but no warning in c,also remember some compilers assume .c extension simply as c but .C as c++,so be careful at such points.otherwise it is a good practice to use const with the case of strings ,so by mistake you don't change the string or try to change a string literal which is stored in read only memory.