Why is conversion from string constant to 'char*' valid in C but invalid in C++

216,549

Solution 1

Up through C++03, your first example was valid, but used a deprecated implicit conversion--a string literal should be treated as being of type char const *, since you can't modify its contents (without causing undefined behavior).

As of C++11, the implicit conversion that had been deprecated was officially removed, so code that depends on it (like your first example) should no longer compile.

You've noted one way to allow the code to compile: although the implicit conversion has been removed, an explicit conversion still works, so you can add a cast. I would not, however, consider this "fixing" the code.

Truly fixing the code requires changing the type of the pointer to the correct type:

char const *p = "abc"; // valid and safe in either C or C++.

As to why it was allowed in C++ (and still is in C): simply because there's a lot of existing code that depends on that implicit conversion, and breaking that code (at least without some official warning) apparently seemed to the standard committees like a bad idea.

Solution 2

It's valid in C for historical reasons. C traditionally specified that the type of a string literal was char * rather than const char *, although it qualified it by saying that you're not actually allowed to modify it.

When you use a cast, you're essentially telling the compiler that you know better than the default type matching rules, and it makes the assignment OK.

Solution 3

You can also use strdup:

char* p = strdup("abc");

or

char p[] = "abc";

as pointed here

Solution 4

You can declare like one of the below options:

char data[] = "Testing String";

or

const char* data = "Testing String";

or

char* data = (char*) "Testing String";
Share:
216,549

Related videos on Youtube

rullof
Author by

rullof

Updated on January 13, 2022

Comments

  • rullof
    rullof over 2 years

    The C++11 Standard (ISO/IEC 14882:2011) says in § C.1.1:

    char* p = "abc"; // valid in C, invalid in C++
    

    For the C++ it's OK as a pointer to a String Literal is harmful since any attempt to modify it leads to a crash. But why is it valid in C?

    The C++11 says also:

    char* p = (char*)"abc"; // OK: cast added
    

    Which means that if a cast is added to the first statement it becomes valid.

    Why does the casting makes the second statement valid in C++ and how is it different from the first one? Isn't it still harmful? If it's the case, why did the standard said that it's OK?

    • chris
      chris over 10 years
      C++11 doesn't allow the first one. I have no idea why C made the type of a string literal char[] in the first place. The second one is a const_cast in disguise.
    • Paul R
      Paul R over 10 years
      There is simply too much legacy C code that would break if this rule were changed.
    • Nawaz
      Nawaz over 10 years
      please quote the text where the Standard says the second is OK.
    • chris
      chris over 10 years
      Ah, discovering context, this discusses the change of the string literal's type. The entire point of that cast is the path of least resistance to backward-compatibility.
    • Casey
      Casey over 10 years
      The C language had string literals before it had const, so they were necessarily not const.
    • Siyuan Ren
      Siyuan Ren over 10 years
      C and C++ allows you to cast from nearly any type to another type. That does not mean these casts are meaningful and safe.
    • autistic
      autistic almost 7 years
      More importantly, this question must be born from some idea that the two languages have more in common than they do. This is proven incorrect by the error message, so why do you think it's a good idea to ask about the two languages as though you expect them to have a common subset? Programming in that common subset is a waste of your time; you'll be relying upon the worst of both worlds. Choose one or the other, and use the linker when you need to link modules from different languages.
  • chris
    chris over 10 years
    It was a char[N] and was changed to const char[N]. It has size information attached to it.
  • Grijesh Chauhan
    Grijesh Chauhan over 10 years
    In C type of string literal is char[N] but not char* e.g. "abc" is char[4]
  • rullof
    rullof over 10 years
    So the second one just gives more flexibility but it's more dangerous?
  • Jerry Coffin
    Jerry Coffin over 10 years
    @rullof: It's dangerous enough that it doesn't give any meaningful flexibility, at least for code that cares (at all) about portability. Writing to a string literal will typically get your program aborted on a modern OS, so allowing code to (try to) write there doesn't add any meaningful flexibility.
  • Daniel Le
    Daniel Le over 7 years
    The code snippet given in this answer char const *p = "abc"; is "valid and safe in both C and C++", not "valid and safe in either C or C++".
  • Caleth
    Caleth about 6 years
    @DanielLe both of those sentences have the same meaning
  • secavfr
    secavfr almost 6 years
    @DanielLe, (true AND true) === true, (true OR true) === true. :l
  • Daniel Le
    Daniel Le almost 6 years
    @FlavienB. I was referring to “either or” in the sense of picking a choice between two choices (google.com/amp/s/dictionary.cambridge.org/amp/british-gramm‌​ar/…).
  • Jerry Coffin
    Jerry Coffin almost 6 years
    Oh my lord! [Insert tongue firmly in cheek] Sorry, but "or" is the correct term here. The code can be compiled as either C or as C++, but cannot be simultaneously compiled as both C and C++. You can choose either, but you must make a choice. You can't have both at once. [resume normal tongue operation].
  • Apollys supports Monica
    Apollys supports Monica over 5 years
    No, both/and is the clearest and most correct wording here. Either/or also happens to convey the right meaning, but it's not as clear technically. Or alone is irrefutably wrong (A or B is not equal to A and B).
  • an offer can't refuse
    an offer can't refuse over 5 years
    According to this post: stackoverflow.com/questions/890535/…, would it be better to use const char *p = "abc"
  • Jerry Coffin
    Jerry Coffin over 5 years
    @buzhidao: To the compiler, char const * and const char * are the same. The one that's different is char *const (which won't work, for the same reason unadorned char * won't work).
  • cartoonist
    cartoonist over 3 years
    Note that "abc" got duplicated and pointer p should be freed to avoid memory leak.
  • user7610
    user7610 over 3 years
    I originally wanted to do a simple cast char* p = (char*)"abcXXXXX"; but my program crashed, because I am actually modifying the string later (I am using mkstemp to replace the X's). This solution worked. And I did not forget to free(p).
  • Toby Speight
    Toby Speight over 3 years
    I'm sure the asker knows this; the question is why C and C++ have different rules here.
  • Toby Speight
    Toby Speight over 3 years
    I'm sure the asker knows this; the question is why C and C++ have different rules here.