33

I have a code like this but I keep receiving this error :

A value of type "const char*" cannot be used to initialize an entity of type "char *"

What is going on?
I have read up on the following threads but have not been able to see any result to my answer as all of them are either from char to char* or char* to char:
Value type const char cannot be used to initialize an entity of type char*
Value of type char* cannot be used to initialize an entity of type "char"

#include <iostream>;
using namespace std;

int main() {
    int x = 0; //variable x created
    int cars (14);//cars is created as a variable with value 14
    int debt{ -1000 };//debt created with value 1000
    float cash = 2.32;
    double credit = 32.32;
    char a = 'a';//for char you must use a single quote and not double
    char* sandwich = "ham";
    return 0;
}

I am using Visual Studio Community 2017

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
nTIAO
  • 415
  • 1
  • 6
  • 15
  • 8
    `const char* sandwich = "ham";` –  Feb 13 '18 at 04:41
  • 2
    which part of the error message you don't understand? it means the initialization (i.e. the right side of your expression) has type `const char*` whereas you declared a `char*`. Just modify the declared type as it said – phuclv Feb 13 '18 at 04:50
  • 1
    Possible duplicate of [Why is conversion from string constant to 'char\*' valid in C but invalid in C++](https://stackoverflow.com/questions/20944784/why-is-conversion-from-string-constant-to-char-valid-in-c-but-invalid-in-c) – xskxzr Feb 13 '18 at 05:01
  • 11
    This is a beginner question, but it’s not a bad question. The fact that `int` is to `const int` as `char*` is to `char* const`, not `const char*`, is not obvious. – Davislor Feb 13 '18 at 05:01
  • 1
    Just so the OP knows, you should avoid "fixing" it this way. `char *sandwich = (char *)"ham";` This works only due to backwards compatibility with C and you are throwing away type safety for no reason. – Justin Randall Feb 13 '18 at 05:05
  • 1
    I fixed this issue in Visual Studio 2019. Right Click Project -> Configuration Properties -> C/C++ -> Language -> Conformance mode = NO (Default is yes/permissive-). This error appeared in a library so there was no way to modify the code. – Juan Rojas Feb 14 '20 at 00:00

3 Answers3

32

That is correct. Let’s say you had the following code:

const char hello[] = "hello, world!";
char* jello = hello; // Not allowed, because:
jello[0] = 'J'; // Undefined behavior!

Whoops! A const char* is a non-const pointer to const char. If you assign its value to a non-const char*, you’ve lost its const property.

A const pointer to non-const char would be a char* const, and you can initialize a char* from that all day if you want.

You can, if you really want, achieve this with const_cast<char*>(p), and I occasionally have, but it’s usually a sign of a serious design flaw. If you actually get the compiler to emit instructions to write to the memory aliased by a string constant, you get undefined behavior. One of the many things that might go wrong is that some implementations will store the constant in read-only memory and crash. Or the same bytes of memory might be re-used for more than one purpose, because after all, we warned you never to change it.

By the way, the rules in C are different. This is solely for backward-compatibility with early versions of C that did not have the const keyword, and you should never write new code that uses a non-const alias to a string constant.

Davislor
  • 14,674
  • 2
  • 34
  • 49
18

You need to make your string literal type const because in C++ it is a constant array of char, unlike C where it is just an array of char. You cannot change a string literal, so making it const is preferred in C++ for extra safety. It is the same reason you have to use an explicit cast when going from const char* to char*. It's still technically "allowed" in C++ since it is allowed in C, which is why it's just a warning. It's still bad practice to do so. To fix the warning, make it const.

const char* sandwich = "ham";
Justin Randall
  • 2,243
  • 2
  • 16
  • 23
1

Your code (and underlying assumption) is valid pre C++11 standard.


String literals (e.g. "ham") since C++11 are of type const char* (or const char[]) if you will instead of char * they used to be. [Always read specs for breaking changes!!!]
Hence the warning in VS 2017. Change the compiler version to pre C++11 version and you will be amazed.

This has subtle nuances and can cause frustrating debug sessions

// C++11 or later

auto c = "Rowdie"; 
// c has type const char*, can't use c to modify literal
c[0] = 'H'; // illegal - CTE

// -vs- 

char * d = "Rowdie";
d[0] = 'H';
cout << d; // outputs "Howdie"

Also another example is auto return type from functions

auto get_literal() {
  // ... function code
  return "String Literal";
}

// and using value later
char* lit = get_literal(); // You get same error as const char* cannot be init to char*

Ravi Tiwari
  • 946
  • 8
  • 17