By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,996 Members | 1,487 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,996 IT Pros & Developers. It's quick & easy.

How to use a const pointer in switch case ?

P: n/a
hi,

I have define in a head file like this:
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)

then I use the constan in switch, like:
switch(font) {
case GLUT_BITMAP_8_BY_13: bitmapHeight = 13;
break;
case GLUT_BITMAP_9_BY_15: bitmapHeight = 15;
break;
case GLUT_BITMAP_TIMES_ROMAN_10: bitmapHeight
= 10; break;
case GLUT_BITMAP_TIMES_ROMAN_24: bitmapHeight
= 24; break;
case GLUT_BITMAP_HELVETICA_10: bitmapHeight =
10; break;
case GLUT_BITMAP_HELVETICA_12: bitmapHeight =
12; break;
case GLUT_BITMAP_HELVETICA_18: bitmapHeight =
18; break;
}
Then I use gcc to compile them, the gcc always complain:

a8.c:261: error: pointers are not permitted as case values
a8.c:261: error: case label does not reduce to an integer constant
a8.c:262: error: pointers are not permitted as case values
a8.c:262: error: case label does not reduce to an integer constant

And I can not convert the GLUT_BITMAP_9_BY_15 to a integer
constant, and can not complain pass, how to solve it?

I know I can use if ... elseif ... statement, really I can not use
switch in this case? switch can just only use a integer constant? I
read the "the C programming language", it said so.

And for what reason the header file will define the const to a
(void *)?

any one can give me a answer?

thanks.

Mar 27 '07 #1
Share this Question
Share on Google+
11 Replies


P: n/a
qu*******@mail.whut.edu.cn said:
hi,

I have define in a head file like this:
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)
Why? That's a daft thing to do.
then I use the constan in switch, like:
switch(font) {
case GLUT_BITMAP_8_BY_13: bitmapHeight = 13;
Can't do that. Case values are supposed to be constant integer
expressions.
Then I use gcc to compile them, the gcc always complain:

a8.c:261: error: pointers are not permitted as case values
Right.
a8.c:261: error: case label does not reduce to an integer constant
Right again.
And I can not convert the GLUT_BITMAP_9_BY_15 to a integer
constant, and can not complain pass, how to solve it?
Use integer constants instead of pointers.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Mar 27 '07 #2

P: n/a
On 3月27日, 下午5时47分, Richard Heathfield <r...@see.sig.invalidwrote:
quakew...@mail.whut.edu.cn said:
hi,
I have define in a head file like this:
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)

Why? That's a daft thing to do.
I do not want to use like that, but that is the glut's head.
(glut is a mini package for opengl.)
Mar 27 '07 #3

P: n/a
qu*******@mail.whut.edu.cn wrote:
hi,

I have define in a head file like this:
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)

And for what reason the header file will define the const to a
(void *)?
The only one I can think of is to antagonise users! What a perverse
thing to do.

--
Ian Collins.
Mar 27 '07 #4

P: n/a
qu*******@mail.whut.edu.cn wrote:

#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)
In <GL/glut.h>. Good grief! Why did they have to do that!

then I use the constan in switch, like:
switch(font) {
case GLUT_BITMAP_8_BY_13: bitmapHeight = 13;
[ ... ]
}
Then I use gcc to compile them, the gcc always complain:
a8.c:261: error: pointers are not permitted as case values
a8.c:261: error: case label does not reduce to an integer constant
And rightly it should. Try casting them to int,

/* Editorial comment about braindamaged interface goes here.
* You should avoid editorial comments in your code, but
* this one is hard to resist.
*/
switch((int)font) {
case (int) GLUT_BITMAP_8_BY_13: bitmapHeight= 13;
/* ... */
}

because I think (int)((void *)3) is an integer constant. You
may need to cast the "font" variable as well, depending on its
declared type.
--
pa at panix dot com
Mar 27 '07 #5

P: n/a
Pierre Asselin wrote:
qu*******@mail.whut.edu.cn wrote:
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)

In <GL/glut.h>. Good grief! Why did they have to do that!

then I use the constan in switch, like:
switch(font) {
case GLUT_BITMAP_8_BY_13: bitmapHeight = 13;
[ ... ]
}
Then I use gcc to compile them, the gcc always complain:
a8.c:261: error: pointers are not permitted as case values
a8.c:261: error: case label does not reduce to an integer constant

And rightly it should. Try casting them to int,

/* Editorial comment about braindamaged interface goes here.
* You should avoid editorial comments in your code, but
* this one is hard to resist.
*/
switch((int)font) {
case (int) GLUT_BITMAP_8_BY_13: bitmapHeight= 13;
/* ... */
}

because I think (int)((void *)3) is an integer constant. You
may need to cast the "font" variable as well, depending on its
declared type.
(int)((void *)3) is not an integer constant expression and cannot be
portably used in a case label. (However, multiple compilers behave as
if it is an integer constant expression and accept such constructs
without any diagnostic.)

Mar 27 '07 #6

P: n/a
(Pierre Asselin) wrote:
>#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
...
In <GL/glut.h>. Good grief! Why did they have to do that!
I saw similar things many times.
It's a side effect of creating opaque data structures, (accessed
trough a void pointer,) and matching a function signature when
providing literal values as parameters to functions expecting those
opaque structures.
(Of course this relies on the assumption that small integers would not
have the same representation as the address of a "real" structure)
For example,
---- in library.h ----

extern void *h1;
extern void *h2;

extern void func1(void *v,...);
extern void func2(void *v,...);

/* valid arguments for func1, func2 ... */

#define H1 (&h1)
#define H2 (&h2)

#define P1 ((void*)1)
#define P2 ((void*)2)

---- In library.c ----

struct hidden
{
...
};

struct hidden h1 = { ... };
struct hidden h2 = { ... };

void func1(void *v, ...)
{
struct hidden *h = (struct hidden*) v;
v-...
...
}

void func2(void *v, ...)
{
struct hidden *h = (struct hidden*) v;
v-...
...
}


Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Mar 27 '07 #7

P: n/a
On Tue, 27 Mar 2007 22:11:26 +0100, Roberto Waltman
<us****@rwaltman.netwrote:
>(Pierre Asselin) wrote:
>>#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
...
In <GL/glut.h>. Good grief! Why did they have to do that!

I saw similar things many times.
It's a side effect of creating opaque data structures, (accessed
trough a void pointer,) and matching a function signature when
providing literal values as parameters to functions expecting those
opaque structures.
(Of course this relies on the assumption that small integers would not
have the same representation as the address of a "real" structure)
For example,
---- in library.h ----

extern void *h1;
extern void *h2;

extern void func1(void *v,...);
extern void func2(void *v,...);

/* valid arguments for func1, func2 ... */

#define H1 (&h1)
#define H2 (&h2)

#define P1 ((void*)1)
#define P2 ((void*)2)

---- In library.c ----
#include "library.h"
struct hidden
{
...
};

struct hidden h1 = { ... };
struct hidden h2 = { ... };

void func1(void *v, ...)
{
struct hidden *h = (struct hidden*) v;
v-...
That should have been h-...

A more useful example:

void func2(void *v, ...)
{
struct hidden *h;
if ((v == P1) || (v == P2))
{
/* do something not using v as */
/* a struct pointer */
...
}
else
{
/* do something using v as */
/* a struct pointer */

h = (struct hidden*) v;
h-...
...
}

Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Mar 27 '07 #8

P: n/a
Roberto Waltman <us****@rwaltman.netwrites:
(Pierre Asselin) wrote:
>>#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
...
In <GL/glut.h>. Good grief! Why did they have to do that!

I saw similar things many times.
It's a side effect of creating opaque data structures, (accessed
trough a void pointer,) and matching a function signature when
providing literal values as parameters to functions expecting those
opaque structures.
(Of course this relies on the assumption that small integers would not
have the same representation as the address of a "real" structure)
[snip]

In fact, the C standard does something similar. The second argument
to the signal() function, and its return value, is of a function
pointer type. The standard defines three macros, SIG_DFL, SIG_ERR,
and SIG_IGN, which are constant expressions of this type. They must
have distinct values unequal to the address of any declarable
function.

<OT>
In the implementations I've checked, they have the values 0, -1, and
1, respectively, converted to the appropriate type (These
implementations allow conversions between integer types and
pointer-to-function types.) Of course, these specific values are not
required.
</OT>

As you say, in both cases this depends on the assumption that small
integers converted to pointers don't match the address of any actual
structure or function. In the case of <signal.h>, the declarations
are part of the implementation, which is free to make whatever
system-specific assumptions it can get away with. The authors of GLUT
apparently chose to make the same kind of assumption, which is not
unreasonable; GLUT probably won't even compile on a DS9K.

If you *don't* want to make that kind of assumption, you could make
the macros expand to the addresses of static structures or functions
that are otherwise unused. For example:

static struct whatever Dummy_GLUT_BITMAP_9_BY_15;
#define GLUT_BITMAP_9_BY_15 ((void*)&Dummy_GLUT_BITMAP_9_BY_15)

...

static void __Dummy_SIG_DFL(int) { abort(); }
/* don't call this function */
#define SIG_DFL (&__Dummy_Sig_DFL)

(The "& is usually unnecessary for a function designator, but in this
case it allows SIG_DFL to be used as the operand of sizeof, and
disallows its use as the operand of another "&".)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 27 '07 #9

P: n/a
Keith Thompson wrote:
Roberto Waltman <us****@rwaltman.netwrites:
(Pierre Asselin) wrote:
>#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
...
In <GL/glut.h>. Good grief! Why did they have to do that!
I saw similar things many times.
It's a side effect of creating opaque data structures, (accessed
trough a void pointer,) and matching a function signature when
providing literal values as parameters to functions expecting those
opaque structures.
(Of course this relies on the assumption that small integers would not
have the same representation as the address of a "real" structure)
[snip]

In fact, the C standard does something similar. The second argument
to the signal() function, and its return value, is of a function
pointer type. The standard defines three macros, SIG_DFL, SIG_ERR,
and SIG_IGN, which are constant expressions of this type. They must
have distinct values unequal to the address of any declarable
function.

<OT>
In the implementations I've checked, they have the values 0, -1, and
1, respectively, converted to the appropriate type (These
implementations allow conversions between integer types and
pointer-to-function types.) Of course, these specific values are not
required.
</OT>
Are you saying implementations are not required to allow conversions
between integer types and pointer-to-function types? I'm aware that
it's allowed that no integer type is large enough to store a function
pointer, but I was under the impression that the conversion itself was
required to be supported -- that is,

int main(void) { return 0 && (int) &main; }

is strictly conforming as far as I know.

Mar 28 '07 #10

P: n/a
"Harald van D某k" <tr*****@gmail.comwrites:
Keith Thompson wrote:
[...]
><OT>
In the implementations I've checked, they have the values 0, -1, and
1, respectively, converted to the appropriate type (These
implementations allow conversions between integer types and
pointer-to-function types.) Of course, these specific values are not
required.
</OT>

Are you saying implementations are not required to allow conversions
between integer types and pointer-to-function types? I'm aware that
it's allowed that no integer type is large enough to store a function
pointer, but I was under the impression that the conversion itself was
required to be supported -- that is,

int main(void) { return 0 && (int) &main; }

is strictly conforming as far as I know.
Yes, that was what I was saying. Alas, I was wrong, wrong, wrong.

C99 6.3.2.3:

An integer may be converted to any pointer type.
[...]
Any pointer type may be converted to an integer type.

What I was thinking of was the fact that function pointers can't be
directly converted to object pointers or vice versa.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 28 '07 #11

P: n/a
Keith Thompson wrote:
"Harald van D某k" <tr*****@gmail.comwrites:
>Keith Thompson wrote:
[...]
>>>
In the implementations I've checked, they have the values 0, -1,
and 1, respectively, converted to the appropriate type (These
implementations allow conversions between integer types and
pointer-to-function types.) Of course, these specific values
are not required.

Are you saying implementations are not required to allow
conversions between integer types and pointer-to-function types?
I'm aware that it's allowed that no integer type is large enough
to store a function pointer, but I was under the impression that
the conversion itself was required to be supported -- that is,

int main(void) { return 0 && (int) &main; }

is strictly conforming as far as I know.

Yes, that was what I was saying. Alas, I was wrong, wrong, wrong.

C99 6.3.2.3:

An integer may be converted to any pointer type.
[...]
Any pointer type may be converted to an integer type.

What I was thinking of was the fact that function pointers can't
be directly converted to object pointers or vice versa.
That emasculated quotation is very dangerous. It might persuade
someone that they can actually do it. The full quote follows.

[#5] An integer may be converted to any pointer type.
Except as previously specified, the result is
implementation-defined, might not be properly aligned, and
might not point to an entity of the referenced type.49)

[#6] Any pointer type may be converted to an integer type.
Except as previously specified, the result is
implementation-defined. If the result cannot be represented
in the integer type, the behavior is undefined. The result
need not be in the range of values of any integer type.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Mar 28 '07 #12

This discussion thread is closed

Replies have been disabled for this discussion.