3

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 ?

Community
  • 1
  • 1
venkysmarty
  • 11,099
  • 25
  • 101
  • 184

5 Answers5

11

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 *.

Lindydancer
  • 25,428
  • 4
  • 49
  • 68
  • problem i am facing is i cannot change the function declaration, it is provided by library, and it takes char*, and i want to pass argument "myarg", how can i pass it – venkysmarty Sep 14 '11 at 11:22
  • 1
    You can silence the warning by casting the pointer to `char *`. You can do this directly on the string literal, or by adding a wrapper function, as suggested by others. – Lindydancer Sep 14 '11 at 11:31
7
char cMessage[] = "add reorganize failed";

This should get rid of the warning.

Jan S
  • 1,831
  • 15
  • 21
  • 2
    This will create a character array, located in RAM, which would occupy precious resources and consume time being initialized. – Lindydancer Sep 14 '11 at 11:16
  • 5
    @Lindydancer If the function requires a char*, it requires a char*. What alternatives are there? (other than changing the function signature) – xanatos Sep 14 '11 at 11:44
  • 5
    @Lindydancer: regarding precious resources, 22 bytes of RAM costs about 2*10^-5 of a penny. If there's any danger at all that the function takes a non-const char* because it modifies the data, then copying the string literal is essential. Slow, correct code is better than fast code that attempts to modify a string literal. – Steve Jessop Sep 14 '11 at 11:47
  • @Steve is it street price, bulk price or what? :-) And is it US penny or UK Penny? – xanatos Sep 14 '11 at 11:49
  • @xantos: It depends... If the function actually writes via the pointer then your solution is the correct one. However, as the function simply use the string to report an error, it is more likely that it doesn't. In that case it's better to simply work around the signature deficiency by casting away the constness of the sting literal. – Lindydancer Sep 14 '11 at 11:53
  • @xanatos: that was a UK penny, first retail result for RAM of any type on scan.co.uk. 2*2GB for 38.88 including VAT. Whatever deal you have with your supplier, though, if you're coding in a context where that amount of stack is "precious" then you'd know about it, and adjust coding style accordingly. It's not something that creeps up on you :-) – Steve Jessop Sep 14 '11 at 11:54
  • 1
    @Steve: In an application you would probably wast more than 22 bytes -- it might not be a big deal in a hosted environment but could be very costly, especially in an embedded environment. Also, if the array is local, it would require initialization every time it is used. – Lindydancer Sep 14 '11 at 11:56
  • 6
    @Lindydancer: so what's your alternative, given that the function can't be changed and we don't know what it does? This answer is right. If there's more information available that could save 22 bytes (or 24 once it's padded) of stack, and the time and code to copy that much data, then great. Someone programming in a restricted environment might think it's worth checking that out to ensure the function doesn't modify the data. But let's not over-sell this by calling that amount of time and memory "precious" when it almost always isn't. – Steve Jessop Sep 14 '11 at 12:07
  • 2
    @Lindydancer: I would note that the message can easily be made static, to avoid the stack waste etc... no assumption should be made on the function body, the signature is the only contract. – Matthieu M. Sep 14 '11 at 12:15
  • @Steve The alternative and the proper solution is in my answer. – Šimon Tóth Sep 14 '11 at 12:41
  • Ok, lets try some new arguments: Say that the function, despite our assumption, really do write via the pointer. In your case, the buffer you passed in will be modified, or even worse overrun. Instead, if you would have passed in a pointer to a string literal, a run-time error would be issued (on most architectures). Clearly, this is better as it would catch errors that would be undetected in approach. – Lindydancer Sep 14 '11 at 17:37
  • @Lindydancer: it's true that if, for example, the documentation for `ErrorMessageInRaphsodyCode` says that `pcMessage` must point to a writable buffer of size at least 23, then Jan's code fails. I disagree with Matthieu -- we are making *some* assumptions about what the function does beyond what its signature says. But Jan makes no assumptions about the buffer size beyond what's already in the question (passing a nul-terminated string). Some implementations put string literals in RO pages, it's true, and on those implementations you could easily test whether the function writes or not. – Steve Jessop Sep 14 '11 at 21:30
2

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.

Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
0

function c_str() of std::string class.

log0
  • 10,489
  • 4
  • 28
  • 62
Artem Chilin
  • 392
  • 2
  • 11
0

(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)
{
//...
}
iammilind
  • 68,093
  • 33
  • 169
  • 336