4

I think the string literals in c++ is the type of const char*. And you can't assign const char* object to a non-constant char* object. But in Visual studio 2010. The following code can compile without errors or warnings, which will however yield a runtime error.

int main(void)
{      
    char *str2 = "this is good";
    str2[0] = 'T';
    cout << str2;
    getchar();
    return 0;
}

And if we don't modify the value of the string, reading the value is ok:

for(char *cp = str2; *cp !=0; ++cp) {
    printf("char is %c\n", *cp);
}
getch();
return 0;

So why can we assign a const char* to a char* here?

Joey.Z
  • 4,492
  • 4
  • 38
  • 63
  • @unkulunkulu The answer is a bit different in C++: according to [lex.string], it's a an _array of const char_ in C++ – dyp Apr 12 '13 at 11:34
  • @DyP, the answer to the linked question covers C++ – unkulunkulu Apr 12 '13 at 11:35
  • @unkulunkulu Oh, sry, you're right. Still, the code above is _invalid_ in C++, see [diff.lex] – dyp Apr 12 '13 at 11:36
  • @DyP, sorry for my ignorance, but what is [diff.lex] :D – unkulunkulu Apr 12 '13 at 11:41
  • @unkulunkulu It's in the C++ Standard (I'm using draft n3485), section C.1.1. – dyp Apr 12 '13 at 11:43
  • n3485 is C++11, right? Yes, looks like it is officially illegal, but compilers still allow it. – unkulunkulu Apr 12 '13 at 11:47
  • @unkulunkulu plz check out my questions highlighted in bold. I think I am not trying to discuss whether it is a const char* or a char*, I focused in the feature of vc++ here. But I think that maybe it's my title here that mislead you. I will make a update. – Joey.Z Apr 12 '13 at 11:48
  • 1
    @DyP - It's unlikely that VC2010 fully follows the C++11 standard. :-) That section is part of the revision of the language, and the conversion was allowed earlier (since the time when C didn't have const). – Bo Persson Apr 12 '13 at 11:49

3 Answers3

5

The question is under VC++, but in GCC it has a meaningful warning:

warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

This warning implies that compiler will apply an implicit conversion despite const/non-const differences. So, this code is OK (without any modification in run-time):

char *str2 = "this is good";

However modifying str2 yields an undefined behavior.

Quentin
  • 62,093
  • 7
  • 131
  • 191
masoud
  • 55,379
  • 16
  • 141
  • 208
1

String literals are, indeed, constant. However, arrays decay to pointers, and you took the non-const pointer to the first element in the array:

char *str2 = "this is good";

Modifying any value of the const char array yields undefined behavior.

This will not compile clean under gcc 4.7.2. If you turn the warning levels up to Warning Level 4 under MSVC, it likely will emit a warning there, too.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • [diff.lex] explicitly states `char* p = "abc";` is invalid in C++. Now I'm confused. – dyp Apr 12 '13 at 11:37
  • @Dyp It's valid in vc++, but you can't modify the value. – Joey.Z Apr 12 '13 at 11:52
  • So the msvc takes the literals as char*, is it correct? – Joey.Z Apr 12 '13 at 11:55
  • 1
    I have just crashed into the fact that MSVS 2013 does not report this as an error, neither with `/W4` nor with `/Wall` nor with `/Wall/W4` — the swine! I am not sure what the difference is between `/W4` and `/Wall`: both are described as pretty much maximal. – PJTraill Aug 25 '15 at 13:32
  • The strange thing is that MSVS Code Analysis has a rule C6298, which I think I am applying (via ‘AllRules’), but that is not triggered by a `return "?";` in a function returning `char*`. – PJTraill Aug 25 '15 at 13:38
  • The insane thing about MSVS is that this even happens with string pooling enabled. – PJTraill Aug 25 '15 at 13:50
1

Let's take a look at C++03 rather than C++11:

[conv.array]

A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”;

Actually, any narrow string literal is of type "array of n const char", but as you can read above, there's a (already in C++03 deprecated) feature to implicitly convert them to rvalues of type char *.

Still you're not allowed to change the content of the string, same as if you had done a const_cast: The object the pointer points to has been declared const, therefore no modification is allowed (undefined behaviour).

dyp
  • 38,334
  • 13
  • 112
  • 177
  • nice! So, still it is const char* but there is a implicit converting. Got it! – Joey.Z Apr 12 '13 at 12:17
  • @zoujyjs Almost. There're two conversions. [conv.array], with text in brackets from me: "abc" is converted [from array of 4 const char] to “pointer to const char” as an array-to-pointer conversion, and then to “pointer to char” as a qualification conversion. – dyp Apr 12 '13 at 12:23