12
void f(char* p)
{}

int main()
{
    f("Hello"); // OK

    auto p = "Hello";

    f(p); // error C2664: 'void f(char *)' : cannot convert parameter 1 
          // from 'const char *' to 'char *'
} 

The code was compiled with VC++ Nov 2012 CTP.

§2.14.15 String Literals, Section 7

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.

Why is f("Hello") OK?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 3
    A more descriptive question would be "Why does my compiler not report an error with `f("Hello")`?" – Drew Dormann Jan 19 '13 at 15:02
  • @DrewDormann -but your title only helps tenOP - for other users the more generic title is of use - +1 for the title – mmmmmm Jan 19 '13 at 19:57
  • @Mark I think the title is fine. The question about "OK" is misleading. – Drew Dormann Jan 19 '13 at 20:07
  • In C, p is an `int`, not a `const char*`. It's been declared with auto scope, but no type (so defaults to `int`). The C tag on this question should be removed. – Paul Hankin Jan 19 '13 at 20:33

4 Answers4

16

This behaviour differs between C and C++, at least in theory.

In C: a string literal decays to a non-const pointer. However, that doesn't make it a good idea; attempting to modify the string through that pointer leads to undefined behaviour.

In C++: it's never ok (AFAIK).* However, some compilers may still let you get away with it. GCC, for example, has the -Wwrite-strings flag, which is enabled by default (at least in 4.5.1 onwards).


* In C++11, at least. (I don't have older specs to hand.)
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • I compiled it as C++ code, but it's OK. – xmllmx Jan 19 '13 at 14:47
  • I agree, in C it's allowed because const wasn't part of the language a long time back, and thus it is allowed to make sure code using literals to pass into functions that are non-const still works. – Mats Petersson Jan 19 '13 at 14:47
  • 2
    just a detail: in C++03 the conversion from literal to char* was supported, but as I recall deprecated; anyway in C++11 it's removed, not valid code – Cheers and hth. - Alf Jan 19 '13 at 14:48
  • Given that the code contains the C++11 `auto` feature, I can't imagine it was compiled with an "older compiler". This answer also doesn't explain why a compiler (old or not) would let you get away with the first usage, but not the second. – sepp2k Jan 19 '13 at 14:49
  • 2
    @sepp2k: Microsoft's compilers have never been good at standards-compliance. –  Jan 19 '13 at 14:51
  • Enable `String Pooling` and you won't be able to write to strings and you'll likely get a warning for the implicit conversion to char* too. – CMircea Jan 19 '13 at 18:41
7
f("Hello");

Even this is not okay in C++. The compiler should give diagnostic, or else it needs to be updated.

In C++, "Hello" is convertible to const char*, not char*.

The conversion from "Hello" to char* is allowed in C++03, though it is deprecated. And in C++11, the conversion is invalid, and the code is ill-formed.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
7

The difference between

f("Hello");

and

f(p);

is that the former involves a literal. In C++03 conversion from string literal to char* (note: not const) was supported. It isn't supported any longer in C++11, but few if any compilers have yet caught up with that rule change.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
-1

I think because auto keyword. it's type deduction so compiler doesn't know it how to convert to char* anymore.

  • That's not the problem. A string literal is `const char*`, not `char*`. `f("Hello")` should be punished with a type error, and it isn't. –  Jan 19 '13 at 14:49