I am learning C++. In the program shown here, as far as I know, str1
and str2
store the addresses of first characters of each of the relevant strings:
#include <iostream>
using namespace std;
int main()
{
char str1[]="hello";
char *str2="world";
cout<<str1<<endl;
cout<<str2<<endl;
}
However, str1
is not giving any warnings, while with str2
I get this warning:
warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
char *str2="world";
What's different between these two declarations that causes the warning in the second case but not the first?
When you write
char str1[] = "hello";
you are saying "please make me an array of char
s that holds the string "hello"
, and please choose the size of the array str1
to be the size of the string initializing it." This means that str1
ends up storing its own unique copy of the string "hello"
. The ultimate type of str1
is char[6]
- five for hello
and one for the null terminator.
When you write
char *str2 = "world";
you are saying "please make me a pointer of type char *
that points to the string literal "world"
." The string literal "world"
has type const char[6]
- it's an array of six characters (five for hello
and one for the null terminator), and importantly those characters are const
and can't be modified. Since you're pointing at that array with a char *
pointer, you're losing the const
modifier, which means that you now (unsafely) have a non-const
pointer to a const
bit of data.
The reason that things are different here is that in the first case, you are getting a copy of the string "hello"
, so the fact that your array isn't const
isn't a problem. In the second case, you are not getting a copy of "hello"
and are instead getting a pointer to it, and since you're getting a pointer to it there's a concern that modifying it could be a real problem.
Stated differently, in the first case, you're getting an honest-to-goodness array of six characters that have a copy of hello
in them, so there's no problem if you then decide to go and mutate those characters. In the second case, you're getting a pointer to an array of six characters that you're not supposed to modify, but you're using a pointer that permits you to mutate things.
So why is it that "world"
is a const char[6]
? As an optimization on many systems, the compiler will only put one copy of "world"
into the program and have all copies of the literal "world"
point to the exact same string in memory. This is great, as long as you don't change the contents of that string. The C++ language enforces this by saying that those characters are const
, so mutating them leads to undefined behavior. On some systems, that undefined behavior leads to things like "whoa, my string literal has the wrong value in it!," and in others it might just segfault.