Deprecated conversion from string constant to char * error [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ deprecated conversion from string constant to ‘char*’
I am having following code, though i didn't copy full code because it is huge.
Following code is in template class, and i am getting warning as below. Because of warning in template i am not able to instantiate it and getting "instantiated from here" error.
warning: deprecated conversion from string constant to 'char*''
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}
char cCompleteMessage[200];
memset(cCompleteMessage, 0x00, sizeof(cCompleteMessage));
char*cMessage = "add reorgenize failed";
ErrorMessageInRaphsodyCode(cCompleteMessage, cMessage, "omcollec.h", __LINE__);
My question is what is best way to get rid of above warning ?

If a function takes a char const *, it guarantees that it only reads whatever data the pointer points to. However, if it takes a non-const pointer, like char *, it might write to it.
As it is not legal to write to a string literal, the compiler will issue a warning.
The best solution is to change the function to accept char const * rather than char *.

char cMessage[] = "add reorganize failed";
This should get rid of the warning.

Best way to get rid of it is to fix the function that is taking the parameter.
If your code is correct and the function does indeed take string constants, it should say so in its prototype:
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, const char* pcFileName, unsigned int RowNo)
If you can't do that (you don't have the code), you can create an inline wrapper:
inline void ErrorMessageInRaphsodyCodeX(char* p1, char* p2, const char* p3, unsigned int p4)
{ ErrorMessageInRaphsodyCode(p1,p2,(char*)p3,p4); }
and use the wrapper instead.
If your code is incorrect and the function does actually require writeable memory (which I highly doubt), you will need to make the string writeable by either creating a local array as Jan suggested, or mallocating enough memory.

(1) Make the variable a const char*
(..., const char* pcFileName, ...)
(2) If above is not possible and you want to retain the state of char* and const char* then make the function a template:
template<typename CHAR_TYPE> // <--- accepts 'char*' or 'const char*'
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, CHAR_TYPE* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}

function c_str() of std::string class.

Related

How to convert string to const unsigned char* without using reinterpret_cast (modern approach)

I have variable input type const std::string&:
const std::string& input
Now I need to convert this to const unsigned char* because this is the input of the function.
Unitl now I have correct code for converting:
reinterpret_cast<const unsigned char*>(input.c_str())
This works well, but in clang I got a warning:
do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
What is the correct way to change a string or const char* to const unsigned char*?
What is the correct way to change a string or const char* to const unsigned char*?
The correct way is to use reinterpret_cast.
If you want to avoid reinterpret_cast, then you must avoid the pointer conversion entirely, which is only possible by solving the XY-problem. Some options:
You could use std::basic_string<unsigned char> in the first place.
If you only need an iterator to unsigned char and not necessarily a pointer, then you could use std::ranges::views::transform which uses static cast for each element.
You could change the function that expects unsigned char* to accept char* instead.
If you cannot change the type of input and do need a unsigned char* and you still must avoid reinterpret cast, then you could create the std::basic_string<unsigned char> from the input using the transform view. But this has potential overhead, so consider whether avoiding reinterpret_cast is worth it.
Edit
Apparently type punning with an union is UB so definitely don't do this.
(Keeping the answer for posterity though!)
To strictly answer your question, there's this way:
void foo(const unsigned char* str) {
std::cout << str << std::endl;
}
int main()
{
std::string word = "test";
//foo(word.data()); fails
union { const char* ccptr; const unsigned char* cucptr; } uword;
uword.ccptr = word.data();
foo(uword.cucptr);
}
Is this any better than a reinterpret_cast? Probably not.

If buffer of bytes should be unsigned char do I have to keep casting all the time?

According to these answers a buffer of bytes should be unsigned char, either because of convention or maybe the padding guarantees, I'm not sure. I have a function that looks something like:
saveDataToFile(const unsigned char* data, size_t size);
I find that I keep having to cast when I have a vector of char or an std::string or a string literal or something, and my code ends up looking like:
const char* text = "text";
saveDataToFile(text, 4); // Argument of const char* is incompatible with parameter of type const unsigned char*
saveDataToFile(reinterpret_cast<const unsigned char*>(text), 4);
Is there a way to avoid doing this all the time? Someone once mentioned to make my function take const char* instead of unsigned, but that doesn't really as then I'd have to cast the other way. For example std::string has .c_str() and .data() that return signed and unsigned. I also thought about taking void*, maybe that's the best way?
Perhaps the simplest way, as you have suggested yourself, is to make the function's first argument a const void* and then cast that to whatever is needed inside the function. This way, you also avoid using a reinterpret_cast and can safely use a static_cast:
void saveDataToFile(const void* data, size_t size)
{
const uint8_t* local = static_cast<const uint8_t*>(data);
//.. do something with the cast pointer ...
}
int main()
{
double dData = 33.3;
int16_t sData = 42;
char cData[] = "Hello, World!";
saveDataToFile(&dData, sizeof(dData));
saveDataToFile(&sData, sizeof(sData));
saveDataToFile(cData, sizeof(cData));
return 0;
}
A more "Pure C++" way (in some folks' eyes, maybe) would be to make a templated function. However, the disadvantages here are: (a) you will need a reinterpret_cast in this case; and (b) the compiler will (probably) generate separate function code for each of the different argument types used:
template<typename T>
void saveDataToFile(const T* data, size_t size)
{
const uint8_t* local = reinterpret_cast<const uint8_t*>(data);
//.. do something with the cast pointer ...
}

Error passing strings as pointers, cannot assign const char* to char* [duplicate]

This question already has answers here:
Errors C2664 and E0167, stumped
(2 answers)
Closed 3 years ago.
I am learning C++ from a textbook (C++: A Beginnners Guide, Second Edition, Herbert Schildt). The following program code is from the book, but results in error, can someone please explain to me why this is not allowed?
The aim is to demonstrate a pointer as a parameter:
#include <iostream>
using namespace std;
char *get_substr(char *sub, char *str); //function prototype
int main()
{
char *substr;
substr = get_substr("three", "one two three four");
cout << "substring found: " << substr;
return 0;
}
I'll not list the function body because it goes as you would expect, but even if it just returns zero, this results in the following error:
E0167 argument of type "const char *" is incompatible with parameter of type "char *", referencing the function call. My understanding is a string is basically an array of char in C anyway, why is this not allowed, and what is a suitable alternative? Thank you in advance.
Your book is old and doesn't conform to the standard anymore, as char* litterals must be const since C++11:
const char *get_substr(const char *sub, const char *str);
Have a look at the curated C++ book list.
String literals like "three" are of const char [N] data-type.
The arguments passed are not compliant with C++11 standards.
The following usage should fix your issue
const char *get_substr(const char *sub, const char *str);
Here is a quick guide for you
https://www.geeksforgeeks.org/difference-const-char-p-char-const-p-const-char-const-p/
Your compiler complains because you are feeding a string literal to a function that may want to modify it.
Presumably, your get_substr() function does not modify the input string, nor the string you are looking for (either of the parameters).
If you know this about your function, you can change its prototype to
const char *get_substr(const char *sub, const char *str);
This has following effects:
the compiler will complain if you try to modify either of the strings in the body of the function
the compiler will be free to assume that your function does not change the data and will not complain when you use const data (such as literals) as parameters for the function

warning: deprecated conversion from string constant to 'char*'' [duplicate]

This question already has an answer here:
C++ warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
(1 answer)
Closed 8 years ago.
I have declared the string array in my code as follows.
char *arr[] ={
"xyz",
"abc",
"pqr",
NULL
};
When compile then got following warning
warning: deprecated conversion from string constant to 'char*''
i know that "xyz" and other string literal are const char and my array is char* so have resolve it by declaring my array const char* arr but i loss the control to point this array in another pointer.
So to resolve above issue have declared array as follows
char *arr[] ={
(char *)"xyz",
(char *)"abc",
(char *)"pqr",
NULL
};
But this type of declaration not fair when need large array (more then 100 string array).
So any one have idea to resolve it by another way.
You don't lose any re-pointing options by making the array a const char* arr[]. Note that there's a huge difference between const char * p (a mutable pointer to an immutable char) and a char * const p (an immutable pointer to a mutable char). This code is perfectly valid:
const char *arr[] = {
"xyz",
"abc",
"pqr",
NULL
};
arr[1] = "ghi";
Live example
There is a difference between a const char* and char *const if your pointer is a const char* you can still point it to another location but you cannot modify the elements it contains. The correct solution in this case is to make the array const char*.
String literals are constant, so you need const pointers to refer to them:
const char *arr[] = {
// whatever
};
Historically, it used to be possible (but dangerous) to convert string literals to non-const char*, for compatibility with ancient code that didn't know about const. This conversion has been deprecated for many years, and finally removed from the language in 2011.

C++ deprecated conversion from string constant to 'char*'

I have a class with a private char str[256];
and for it I have an explicit constructor:
explicit myClass(char *func)
{
strcpy(str,func);
}
I call it as:
myClass obj("example");
When I compile this I get the following warning:
deprecated conversion from string constant to 'char*'
Why is this happening?
This is an error message you see whenever you have a situation like the following:
char* pointer_to_nonconst = "string literal";
Why? Well, C and C++ differ in the type of the string literal. In C the type is array of char and in C++ it is constant array of char. In any case, you are not allowed to change the characters of the string literal, so the const in C++ is not really a restriction but more of a type safety thing. A conversion from const char* to char* is generally not possible without an explicit cast for safety reasons. But for backwards compatibility with C the language C++ still allows assigning a string literal to a char* and gives you a warning about this conversion being deprecated.
So, somewhere you are missing one or more consts in your program for const correctness. But the code you showed to us is not the problem as it does not do this kind of deprecated conversion. The warning must have come from some other place.
The warning:
deprecated conversion from string constant to 'char*'
is given because you are doing somewhere (not in the code you posted) something like:
void foo(char* str);
foo("hello");
The problem is that you are trying to convert a string literal (with type const char[]) to char*.
You can convert a const char[] to const char* because the array decays to the pointer, but what you are doing is making a mutable a constant.
This conversion is probably allowed for C compatibility and just gives you the warning mentioned.
As answer no. 2 by fnieto - Fernando Nieto clearly and correctly describes that this warning is given because somewhere in your code you are doing (not in the code you posted) something like:
void foo(char* str);
foo("hello");
However, if you want to keep your code warning-free as well then just make respective change in your code:
void foo(char* str);
foo((char *)"hello");
That is, simply cast the string constant to (char *).
There are 3 solutions:
Solution 1:
const char *x = "foo bar";
Solution 2:
char *x = (char *)"foo bar";
Solution 3:
char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");
Arrays also can be used instead of pointers because an array is already a constant pointer.
Update: See the comments for security concerns regarding solution 3.
A reason for this problem (which is even harder to detect than the issue with char* str = "some string" - which others have explained) is when you are using constexpr.
constexpr char* str = "some string";
It seems that it would behave similar to const char* str, and so would not cause a warning, as it occurs before char*, but it instead behaves as char* const str.
Details
Constant pointer, and pointer to a constant. The difference between const char* str, and char* const str can be explained as follows.
const char* str : Declare str to be a pointer to a const char. This means that the data to which this pointer is pointing to it constant. The pointer can be modified, but any attempt to modify the data would throw a compilation error.
str++ ; : VALID. We are modifying the pointer, and not the data being pointed to.
*str = 'a'; : INVALID. We are trying to modify the data being pointed to.
char* const str : Declare str to be a const pointer to char. This means that point is now constant, but the data being pointed too is not. The pointer cannot be modified but we can modify the data using the pointer.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : VALID. We are trying to modify the data being pointed to. In our case this will not cause a compilation error, but will cause a runtime error, as the string will most probably will go into a read only section of the compiled binary. This statement would make sense if we had dynamically allocated memory, eg. char* const str = new char[5];.
const char* const str : Declare str to be a const pointer to a const char. In this case we can neither modify the pointer, nor the data being pointed to.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : INVALID. We are trying to modify the data pointed by this pointer, which is also constant.
In my case the issue was that I was expecting constexpr char* str to behave as const char* str, and not char* const str, since visually it seems closer to the former.
Also, the warning generated for constexpr char* str = "some string" is slightly different from char* str = "some string".
Compiler warning for constexpr char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *const'
Compiler warning for char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'.
Tip
You can use C gibberish ↔ English converter to convert C declarations to easily understandable English statements, and vice versa. This is a C only tool, and thus wont support things (like constexpr) which are exclusive to C++.
In fact a string constant literal is neither a const char * nor a char* but a char[]. Its quite strange but written down in the c++ specifications; If you modify it the behavior is undefined because the compiler may store it in the code segment.
Maybe you can try this:
void foo(const char* str)
{
// Do something
}
foo("Hello")
It works for me
I solve this problem by adding this macro in the beginning of the code, somewhere. Or add it in <iostream>, hehe.
#define C_TEXT( text ) ((char*)std::string( text ).c_str())
I also got the same problem. And what I simple did is just adding const char* instead of char*. And the problem solved. As others have mentioned above it is a compatible error. C treats strings as char arrays while C++ treat them as const char arrays.
For what its worth, I find this simple wrapper class to be helpful for converting C++ strings to char *:
class StringWrapper {
std::vector<char> vec;
public:
StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
}
char *getChars() {
return &vec[0];
}
};
The following illustrates the solution, assign your string to a variable pointer to a constant array of char (a string is a constant pointer to a constant array of char - plus length info):
#include <iostream>
void Swap(const char * & left, const char * & right) {
const char *const temp = left;
left = right;
right = temp;
}
int main() {
const char * x = "Hello"; // These works because you are making a variable
const char * y = "World"; // pointer to a constant string
std::cout << "x = " << x << ", y = " << y << '\n';
Swap(x, y);
std::cout << "x = " << x << ", y = " << y << '\n';
}