Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where in the C++11 Standard does it say that char* p = "abc"; is ill-formed?

Where in the C++11 Standard does it say that char* p = "abc"; is ill-formed?

like image 516
Wake up Brazil Avatar asked Feb 17 '23 00:02

Wake up Brazil


1 Answers

This was still valid in C++03 (although deprecated), but things have changed in C++11. Annex C of the C++11 Standard mentions (see C1.1) that:

Change: String literals made const

The type of a string literal is changed from “array of char” to “array of const char.” The type of a char16_t string literal is changed from “array of some-integer-type” to “array of const char16_t.” The type of a char32_t string literal is changed from “array of some-integer-type” to “array of const char32_t.” The type of a wide string literal is changed from “array of wchar_t” to “array of const wchar_t.”

Rationale: This avoids calling an inappropriate overloaded function, which might expect to be able to modify its argument.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Syntactic transformation. The fix is to add a cast:

char* p = "abc"; // valid in C, invalid in C++
void f(char*) {
    char* p = (char*)"abc"; // OK: cast added
    f(p);
    f((char*)"def"); // OK: cast added
}

In C++03, this was an exception to the implicit conversion rules. In C++11, this exception is gone, which is perhaps why you couldn't find the point in the Standard where this case is mentioned.

The paragraph quoted above has been added to Annex C (which is only informative, not normative) so that you could find evidence of the breaking change.

Anyway, the relevant paragraphs are 2.14.5/8:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).

And 4.4/1 (see also 4.2 for array-to-pointer conversions):

A prvalue of type “pointer to cv1 T” can be converted to a prvalue of type “pointer to cv2 T” if “cv2 T” is more cv-qualified than “cv1 T”.

like image 110
Andy Prowl Avatar answered Feb 27 '23 14:02

Andy Prowl