"Warning: deprecated conversion from string constant to *char" - help me understand...

Hello, on the following code, I get the warning in the title... i.e. "deprecated conversion from string constant to *char". I'm trying to understand the error and resolve it... it doesn't seem to be a huge problem, but I don't like having errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
//Function to read in an array.
void read(char prompt[], int SIZE, char result[])
{
    cout << prompt; //Displays out the incoming prompt.
    cin.get(result, SIZE, '\n'); //Reads in character input.
    cin.ignore(100, '\n'); //Clears input buffer.
}

...

    read("Enter phrase to be stored (130 chars max): \n", SIZE, initPhrase);

...


The line after the ellipses is the line that gets the error... any ideas?
void read( const char prompt[], int SIZE, char result[])

Otherwise it would be possible to change (in function read()) a character array which is a constant in the call to the function.
Hmm, that caused some other problems (undefined reference 'read(char*, int, char*)), I guess I'll just deal with the error for now and wait until we get into pointers.
Then you may also have called it a different time with a non-const array.

You really need to give complete compileable code - we can't second-guess what you are doing elsewhere.
Last edited on
visual studio likes to say things are deprecated when there is a microsoftism replacement.
Those are warnings, not errors.
other times this error comes up is code that worked with less strict, older compilers or things like g++ with no options (it will compile just about anything remotely like c++ in that mode). Depending on the compiler flags this can be warning or error, and also depending on what it was.

generally, though, if you are using c-strings (try to use string instead) do not do this
char * c = "blah"; //this sets off alarms and there is no reason to do it.
do this instead:
char c[] = "blah"; //exactly sized to this string and cannot grow to hold bigger strings.
or
char c[1000] = "blah"; //has tons of space for more letters later.

in these examples, c can be treated as if it were a char * for most purposes (but you can't new it, which is not useful anyway for c-strings in most code). You only need new / pointers if your strings are huge (think: pulled all the letters from a 3gb xml file into one string) or you have a LOT of them (running out of stack space, which takes a LOT to accomplish).

in your example, consider getline?
Last edited on
> visual studio likes to say things are deprecated when there is a microsoftism replacement.
> Those are warnings, not errors.

It is an error.
An ordinary string literal has type “array of n const char” where n is the size of the string ...
https://eel.is/c++draft/lex.string#6


1
2
3
4
5
6
int main()
{
    // *** error: ISO C++ forbids converting a string constant to 'char*' (GNU)
    // *** error: ISO C++11 does not allow conversion from string literal to 'char *' (LLVM)
    char* wrong = "string literal" ;
}

http://coliru.stacked-crooked.com/a/68a97b748699a2fd

It was deprecated in legacy C++.
In C, string literals are of type char[], and can be assigned directly to a (non-const) char*. C++03 allowed it as well (but deprecated it, as literals are const in C++). C++11 no longer allows such assignments without a cast.
https://en.cppreference.com/w/cpp/language/string_literal

Hmm, that caused some other problems
(undefined reference 'read(char*, int, char*))

Let me guess: You have both declaration void read( const char prompt[], int SIZE, char result[] );
and definition
1
2
3
4
5
6
void read( const char prompt[], int SIZE, char result[] )
{
    cout << prompt; //Displays out the incoming prompt.
    cin.get(result, SIZE, '\n'); //Reads in character input.
    cin.ignore(100, '\n'); //Clears input buffer.
}

and forgot to update both.
Last edited on
To understand why this frustrating warning occurs, let's suppose that the warning didn't occur and consider this code:
1
2
3
4
5
6
7
8
9
void foo(char *cp) {
    cp[0] = 'B';   // modify the first character
}

int main()
{
    foo("Hello World");
    std::cout << "Hello World" << std::endl;
}


The compiler might store "Hello World" in read-only memory. Maybe it's compiling for a small device like a hand-held calculator where there is 128K of ROM but only 2K of RAM. "Hello World" is a string literal after all - it won't change. But now foo() tries to change it. Bam - the program tries to modify read-only memory and crashes.

Next let's consider what happens if you store "Hello World" in RAM. There's no reason that each instance of "Hello World" must be separate (I'm pretty sure this is in the standard but someone with more knowledge would have to say). So you call foo("Hello World") and it changes the string to "Bello world". Then main() tries to print "Hello World" and ends up printing "Bello World" instead!! Good luck finding THAT bug. :)

So string literals are const. You can't modify them because Bad Things will happen if you do. A function that takes char * as a parameter is telling the compiler that it might modify the string, so the compiler doesn't allow that.
It (attempted conversion from narrow string literal to char* without a cast) is not just a warning; it is an error.
The program is ill-formed.

Attempting to modify an object of a const-qualified type (via a cast) engenders undefined behaviour;
even if the object of the const-qualified type is stored in hardware-writable memory.
Last edited on
Topic archived. No new replies allowed.