How to char* = "string literal" appropriately.

One of my favorite tactics is broken :-(

Please help me fix it.

In some code I like to keep a lightweight trace point for debugging and monitoring purposes.

The easy way to do this is to create a char* at the top of the function (or perhaps in the object) and assign a string literal to that pointer representing what is happening "right now" in the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void example() {
  char* WhereWeAre = "example().top";
  try {
    // do stuff
    WhereWeAre = "example().DoingStuff";
    ...
    // do more stuff
    WhereWeAre = "example().DoingMoreStuff";
    ...
    // and so forth
  }
  catch(...) {
    throw FancyException(WhereWeAre);
  }
}


Trouble is with the latest g++ I get:

warning: deprecated conversion from string constant to char*

--

So my question is this:

Within the confines of this new standard how _should_ I implement this or similar practices?

I want to avoid const_cast since it's use tends to raise red flags, but I want to keep the functionality of inexpensively assigning strings to a pointer.

On the other hand is this an appropriate place to use const_cast ?

All ideas welcome.

Thanks!

_M

Last edited on
I dont see the problem. A warning is someting else as an error: there is nothing wrong with it, the compiler just tells you that you're conversing data from one data type to another, because this may be not be what you want.
However, in this case you want it, so you dont need to chance it. If everyting else is allright, it will compile.

Ps. This is based on your error. I havent actually tested your code, so if I'm missing someting, sorry for that.
I understand that because this is a warning it is ok to leave the code as it is.

My question is a bit more philosophical and also goes to perceived code quality. Code which compiles with warnings is perceived as being of lesser quality than code which does not produce warnings.

Doesn't the warning indicate that this is not the best way to do this?

If so then what would be the best way -- specifically the best way to accomplish the goal without raising the warning?

What is the "right way" to get this done within the standard?

The folks developing the standard must have considered this kind of code (though I don't have a handy reference to that discussion).

What is the best current thinking on how to handle this case?
You could use something like strcpy() sprintf() or you could own function to dinamically create a new char array
and filling it with wanted chars or you could use std::strings and .c_str()
Last edited on
You should change your char* variable to const char*.
That would defeat the purpose of using a char* as the status flag.

Making a copy of the string is a comparatively expensive operation.

Assigning a pointer value is both atomic and inexpensive - like making an integer assignment.

Also, I think char* = std:string.c_str() poses the same const-ness problem.

The char* in this case is the equivalent of a numeric symbol for a particular state where that state can be represented as a string. Change the state is a lightweight operation--- just change the number (in this case a pointer).
It's the same thing either way.

Change char* WhereAreWe to const char* WhereAreWe and the code still compiles and works just as it used to.

No need for string copies.
I really didn't think that would work, but it did.

The following works just fine and does what I intended.
(Tested w/ g++ version 3.4.6, not the latest)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// constgrief.cpp

#include <iostream>

using namespace std;

int main(int argc, char* argv[]) {

    const char* WhereWeAre = "We are here";

    cout << WhereWeAre << endl;

    WhereWeAre = "Now we are there";

    cout << WhereWeAre << endl;

    WhereWeAre = "Now we are neither here nor there";

    cout << WhereWeAre << endl;

    WhereWeAre = "All Done";

    cout << WhereWeAre << endl;

    return 0;
}


I thought that having defined WhereWeAre as const char* I would be able to assign it once, and then never again. I was wrong.

The secret is in how const is used. As written above, WhereWeAre is "a pointer to a constant character".

In order to create the problem I thought I was going to have WhereWeAre needs to be defined this way:

 
const char* const WhereWeAre = "We are here";


or

 
char* const WhereWeAre = "We are here";


Which will give the following compile errors:

constgrief.cpp: In function `int main(int, char**)':
constgrief.cpp:13: error: assignment of read-only variable `WhereWeAre'
constgrief.cpp:17: error: assignment of read-only variable `WhereWeAre'
constgrief.cpp:21: error: assignment of read-only variable `WhereWeAre'

The trick is in clearly understanding how const syntax works. When const is directly in front of the variable name then the variable itself becomes constant.

I was stuck in a paradigm and didn't see the solution right in front of me.

Thanks for digging me out!

Last edited on
Topic archived. No new replies allowed.