Initializing enum with strings

R

Russell Shaw

Hi,
gcc-3.4 complains about non-integers in:

enum {IDENTIFIER = "<identifier>", WIDGETDEF = "widgetdef"};

even if i cast the strings to integers.
 
R

Richard Bos

Russell Shaw said:
gcc-3.4 complains about non-integers in:

enum {IDENTIFIER = "<identifier>", WIDGETDEF = "widgetdef"};

And so it should. Enumeration constants can only have integral values.
If you want enum constants with string values, you're probably trying to
do something which you needn't, or shouldn't, do. Why would you need
such constants in the first place?
even if i cast the strings to integers.

That doesn't even make sense. What would you cast to integer, a pointer
to a string literal? That's possible, in theory - but it doesn't make
sense. The value will be useless.

Richard
 
C

Chris Dollin

Russell said:
Hi,
gcc-3.4 complains about non-integers in:

enum {IDENTIFIER = "<identifier>", WIDGETDEF = "widgetdef"};

even if i cast the strings to integers.

Well, what did you expect?

The enum identifiers have integer values. Casting a string
to an integer doesn't get you anything terribly interesting
or reliable.
 
R

Russell Shaw

Richard said:
And so it should. Enumeration constants can only have integral values.
If you want enum constants with string values, you're probably trying to
do something which you needn't, or shouldn't, do. Why would you need
such constants in the first place?

Because i'm using the constants in a lexer, and they can do double duty
for error message printouts. I need to use them multiple places in the
code, and if i use the strings directly, i'm not guaranteed to get the
same pointer value every time.
That doesn't even make sense. What would you cast to integer, a pointer
to a string literal? That's possible, in theory - but it doesn't make
sense. The value will be useless.

Richard

char *str = "abcd"; declares a pointer to a string, so i wanted to
use pointers like this as inits for the enum.
 
W

William Ahern

Russell Shaw said:
Hi,
gcc-3.4 complains about non-integers in:

enum {IDENTIFIER = "<identifier>", WIDGETDEF = "widgetdef"};

even if i cast the strings to integers.

Enum's can't be pointers, only integers. The typical solution is to map
the enum string description to the enum itself using an array:

In C89, assuming your enums are sequential and start from zero

const char *enummap[] = {
"<identifier>",
"widgetdef",
};

and in C99, assuming nothing but the usual constraints

const char *enummap[] = {
.[WIDGETDEF] = "widgetdef",
.[IDENTIFIER] = "<identifier>",
};

(Note that the array will be as large as your largest enum, so this might
not work out well if your enums are meant to be utilized bitwise.)

- Bill
 
M

Me

gcc-3.4 complains about non-integers in:
Because i'm using the constants in a lexer, and they can do double duty
for error message printouts. I need to use them multiple places in the
code, and if i use the strings directly, i'm not guaranteed to get the
same pointer value every time.

const char * const IDENTIFIER = "<identifier>";

Now you are guaranteed (and you really don't want to use the string
constant directly anyway, your compiler can't warn against inadvertant
typos that way). Even if your implementation allows something that
questionable, it doesn't guarantee they can be casted back to a string
or even that are distinct values when casted to an integer type. For
what you're trying to do, I would probably do something like:

#define TOKEN(F) \
F(IDENTIFIER, "<identifier>") \
F(WIDGETDEF, "widgetdef")

#define tok(a,b) a = b,
enum Token {
TOKEN(tok)
NUM_TOKENS
};
#undef tok

#define tok(a,b) b,
const char * const token2str[NUM_TOKENS] = {
TOKEN(tok)
};
#undef tok
 
L

Lawrence Kirby

const char * const IDENTIFIER = "<identifier>";

However you're creating an unnecessary pointer object here. Better is:

static const char IDENTIFIER[] = "<identifier>";

A string literal is essentially an unnamed static array of char, all you
need to do is create a named version, as this does.

Lawrence
 
D

Dave Thompson

<snip> For what you're trying to do, I would probably do something like:

#define TOKEN(F) \
F(IDENTIFIER, "<identifier>") \
F(WIDGETDEF, "widgetdef")

#define tok(a,b) a = b,
enum Token {
TOKEN(tok)
NUM_TOKENS
};
#undef tok

#define tok(a,b) b,
const char * const token2str[NUM_TOKENS] = {
TOKEN(tok)
};
#undef tok

Obviously you meant #define tok(a,b) a, in the first case
and #define tok(a,b) [a] = b, or just b, in the second.

- David.Thompson1 at worldnet.att.net
 
R

Russell Shaw

Dave said:
<snip> For what you're trying to do, I would probably do something like:

#define TOKEN(F) \
F(IDENTIFIER, "<identifier>") \
F(WIDGETDEF, "widgetdef")

#define tok(a,b) a = b,
enum Token {
TOKEN(tok)
NUM_TOKENS
};
#undef tok

#define tok(a,b) b,
const char * const token2str[NUM_TOKENS] = {
TOKEN(tok)
};
#undef tok


Obviously you meant #define tok(a,b) a, in the first case
and #define tok(a,b) [a] = b, or just b, in the second.

- David.Thompson1 at worldnet.att.net

You should be able to cast a const string pointer to an int so that
one could do: enum {an_enum = (int)"the first enum"}. It's cleaner
than #defines.
 
K

Keith Thompson

Russell Shaw said:
You should be able to cast a const string pointer to an int so that
one could do: enum {an_enum = (int)"the first enum"}. It's cleaner
than #defines.

gcc complains "enumerator value for `an_enum' not integer constant".

The message is actually slightly misleading; it has to be a constant
expression, not an integer constant. But gcc is correct; a cast of an
address cannot be part of an integer constant expression.

You can convert a pointer to an int in a context that doesn't require
a constant expression, but the result is not necessarily useful. For
example, if pointers are 8 bytes and ints are 4 bytes, two distinct
pointer values might convert to the same int value.
 
P

Peter Nilsson

The type of "the first enum" is not const qualified.
gcc complains "enumerator value for `an_enum' not integer constant".

The message is actually slightly misleading; it has to be a constant
expression, not an integer constant.

More precisely, it must be an integer constant expression.
But gcc is correct; a cast of an address cannot be part of an integer
constant expression.

You can convert a pointer to an int in a context that doesn't require
a constant expression, but the result is not necessarily useful. For
example, if pointers are 8 bytes and ints are 4 bytes, two distinct
pointer values might convert to the same int value.

This notwithstanding, and as has been pointed out elsethread, there's
always...

const char the_first_enum[] = "the first enum";

Synchronising enums and strings has also been discussed in clc before.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top