Constant memory table doesn't reduce to int in switch statement,why?

R

Remco Poelstra

Hi,

I've the following piece of code:

enum {
PLAY,
STOP,
PAUSE
};

struct command {
unsigned char bytecode;
unsigned char arguments;
char *name;
};

struct command slink_commands[] = {
{0x00,0,"Play"},
{0x01,0,"Stop"},
{0x02,0,"Pause"},
};


int main(void) {

switch(1) {
case slink_commands[PLAY].bytecode:
break;
}
return 0;
}


My compiler now gives the warning that the case label doesn't reduce to
an integer constant. Why? The value is known at compile time...
Is this construction impossible, or can I tell my compiler some way that
it IS a constant?

(I'm using GCC 3.3.1, but I think it's more a C problem, than a GCC
problem, so I ask here. Sorry if this is the wrong place....)


Thanks in advance,

Remco Poelstra
 
M

Martin Ambuhl

Hi,

I've the following piece of code:

enum {
PLAY,
STOP,
PAUSE
};

struct command {
unsigned char bytecode;
unsigned char arguments;
char *name;
};

struct command slink_commands[] = {
{0x00,0,"Play"},
{0x01,0,"Stop"},
{0x02,0,"Pause"},
};


int main(void) {

switch(1) {
case slink_commands[PLAY].bytecode:
break;
}
return 0;
}


My compiler now gives the warning that the case label doesn't reduce
to an integer constant. Why?

Because it's a variable.
The value is known at compile time...

Its initial value is known. It is still a variable.
Is this construction impossible, or can I tell my compiler some way
that it IS a constant?

You have a lookup table defined, so look up the value. "switch" is not
supposed to be the answer to every problem.
(I'm using GCC 3.3.1, but I think it's more a C problem, than a GCC
problem, so I ask here.

You're right. Your code is invalid C, no matter what gcc or some other
compiler might do with it.
 
E

Emmanuel Delahaye

In 'comp.lang.c' said:
Hi,

I've the following piece of code:

enum {
PLAY,
STOP,
PAUSE
};

struct command {
unsigned char bytecode;
unsigned char arguments;
char *name;
};

struct command slink_commands[] = {
{0x00,0,"Play"},
{0x01,0,"Stop"},
{0x02,0,"Pause"},
};

Why not

struct command slink_commands[] = {
{PLAY,0,"Play"},
{STOP,0,"Stop"},
{PAUSE,0,"Pause"},
};

? Sounds more consistent and maintainable, isn't it?
int main(void) {

switch(1) {
case slink_commands[PLAY].bytecode:

A twisted and wrong way of writing:

case PLAY:
break;
}
return 0;
}


My compiler now gives the warning that the case label doesn't reduce to
an integer constant. Why? The value is known at compile time...

It's true. 'slink_commands[PLAY].bytecode' is far to be a 'constant
integer expression', because 'slink_commands' is an initialized variable.
Even with 'const', it will still be a (read-only) variable.

Constant integer expressions are made of integers, enums, integer macros and
arithmetic or bitwise operators.
 
D

Daniel Haude

On Mon, 30 Jun 2003 22:40:21 +0200,
in Msg. said:
I've the following piece of code:

enum {
PLAY,
STOP,
PAUSE
};

struct command {
unsigned char bytecode;
unsigned char arguments;
char *name;
};

struct command slink_commands[] = {
{0x00,0,"Play"},
{0x01,0,"Stop"},
{0x02,0,"Pause"},
};


int main(void) {

switch(1) {
case slink_commands[PLAY].bytecode:
break;
}
return 0;
}

Others already have pointed out why this doesn't work in C. But I think
this is not even what you'd /want/ to write, even if it did work. Actually
the whole point of constructing lookup tables (usually in connection with
function pointers) is to avoid switch statements. But anyway, here's what
you probably wanted to write (having added an element MAX_COMMANDS to
your enum):

/* UNTESTED CODE JUST TYPED IN NEWSREADER */

int main(void)
{
int i;
int code;

code = get_bytecode_from_somewhere();
for (i = 0; i < MAX_COMMANDS; i++) {
if (code == slink_commands.bytecode) {
break;
}
}
switch (i) {
case PLAY : /* play */ break;
case STOP : /* ... etc... */ break;
/* ... */
case MAX_COMMANDS : /* invalid bytecode */ break;
default : /* IMPOSSIBLE */
}
}

Obviously performance-wise it doesn't make too much sense to first have a
loop iteratig over several possible bytecodes to find the lookuop table
index, and then switching on that index. But it's pretty much all you can
do with your table at the moment.

--Daniel
 
R

Remco Poelstra

Thanks for all the replies.

I thought that such a table would be nice with a switch statement, but I
'll follow your common advice and try it without the switch statement
(using function pointers).
It wil at least save me some line or 45 to construct the switch.

Thanks again,

Remco Poelstra
 
P

Peter Shaggy Haywood

Groovy hepcat Remco Poelstra was jivin' on Mon, 30 Jun 2003 22:40:21
+0200 in comp.lang.c.
Constant memory table doesn't reduce to int in switch statement,
why?'s a cool scene! Dig it!
switch(1) {
^
Another point, which noone else mentioned: you have a constant
expression for the value being tested. An integer literal, such as the
above 1, is a constant expression. This makes no sense. The idea
behind a switch statement is that it tests the value of an expression
that may have either of several values (to determine which of those
several values it has). Obviously a constant expression can only have
one value, so testing it in such a way is pointless.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top