9

I recently installed VS 2017, and have ran into a weird sort of issue. Basically, I cannot use hard-coded strings without explicitly casting them to (char*). If I said something like Function("test"), it would simply throw an error stating that const char* is incompatible with char*. I really don't want to stick with VS 2015 :(. Anybody know how to make VS recognize that these are the same thing?

Thanks a lot in advance.

Jordan
  • 440
  • 2
  • 5
  • 14
  • 3
    `const char*` and `char*` are very different things. Casting them to `char*` is not allowed – Justin Feb 01 '18 at 02:59
  • @Justin Sorry, I don't really understand what you are saying. Why is it that the **exact** same code will work in VS 2015? And yes, you can explicitly cast it to char*... I have a feeling you may have misunderstood my question. Even if I typed something like: `char* test = "hi"` it throws an error – Jordan Feb 01 '18 at 03:05
  • According to Clang compiler warning, ISO C++17 doesn't accept casting of string literal to char*. Your VS might somehow make it the default – An Hoa Feb 01 '18 at 03:14
  • @AnHoa Strange I just tested it on my computer and it compiles fine with c++17. – James Nguyen Feb 01 '18 at 03:16
  • You can indeed cast any pointer to any other pointer, but dereferencing the castes pointer is usually UB. In this case, casting away constness allows you to write to a const array, which is UB. – Cris Luengo Feb 01 '18 at 03:17
  • 2
    @Jordan It worked because MSVS 2015 allowed you to be naughty. A string literal is a `const char[N]` and trying to pass that to a `char*` violates const correctness. Instead of trying to subvert that you should make your code standard conforming. Also consider using `std::string` or `std::string_view` instead of c-strings. – NathanOliver Feb 01 '18 at 03:22
  • @NathanOliver This may be completely false, but I have always made the assumption that std::string was far less efficient. I don't know why, and this might be really stupid, but I just assumed it to be a more complex data-type. Otherwise, I will move on and start using it. – Jordan Feb 01 '18 at 03:25
  • 2
    @Jordan Your right that `std::string` is less efficient but generally this wont be a bottle neck unless you are working with a lot of string especially since we have SSO(short string optimization). `std::stting_view` is read only and is pretty much a pointer and a size(no allocation) so you can thing of it as a safe `char*` – NathanOliver Feb 01 '18 at 03:29

2 Answers2

14

VisualStudio 2017 15.5 started setting the /permissive- flag for all new solutions, which disallows the implicit conversion of string literals to non-const char*. You can edit the solution's properties to disable that flag while you update your codebase to conform to the C++ standard. It's listed as "Conformance mode" in the "Language" tab under "C/C++" in the project's properties.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • Link to documentation: https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance – Justin Feb 01 '18 at 03:19
  • Aha! You saved my life! I am no longer stuck in the stone-ages of VS 2015 :D – Jordan Feb 01 '18 at 03:22
  • 2
    @Jordan: Unfortunately it's your code in the stone age. Const-correct code will be accepted just fine by both VS 2015 and 2017 (most correct code will in general be accepted all the way back to 2002) Try to at least start using `const` in your new code, when a function accepts a pointer that it won't be writing through. – Ben Voigt Feb 01 '18 at 05:33
  • Right... I did my research and came to that conclusion haha – Jordan Feb 02 '18 at 03:23
3

You shouldn't assign or cast string literals to char*, because it's illegal to modify a string literal, even through a pointer to non-const char.

The incorrect behavior where string literals can be implicitly converted to char* was allowed, but deprecated, in the C++98 (and C99) standards, but removed in the C++11 and C11 standards.

Assigning a string literal to an array variable has value (copy) semantics, as opposed to the reference semantics of pointer variables, so you can assign a string literal to an array of non-const char, and modify that.

char mutable_string[] = "tha string";
mutable_string[2] = 'e'; // OK

Array variables are more useful than pointer variables because they preserve size information at compile-time, so it's better to define an immutable C string like

constexpr char immutable_string[] = "the immutable string";
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
Ray Hamel
  • 1,289
  • 6
  • 16