I am perfectly aware of the mechanism behind the switch
statement and why an integer constant is required. What I don't undestand is why the following case
label is not considered an integer constant. What is it then? A non-existing variable? Can anyone categorize it? Does the C compiler really need to be so dumb?
struct my_struct {
const int my_int;
};
switch (4) {
case ((struct my_struct) { 4 }).my_int:
printf("Hey there!\n");
break;
}
And of course…
error: case label does not reduce to an integer constant
case ((struct my_struct) { 4 }).my_int:
EDIT to answer to Eugene's comment:
What's you real use case? If it is an integer constant, why to make it so complicated?
I was trying to find a clever hack to switch between two-character strings, using a union
instead of a struct
, as in the following example:
#include <stdio.h>
union my_union {
char my_char[sizeof(int)];
int my_int;
};
void clever_switch (const char * const my_input) {
switch (((union my_union *) my_input)->my_int) {
case ((union my_union) { "hi" }).my_int:
printf("You said hi!\n");
break;
case ((union my_union) { "no" }).my_int:
printf("Why not?\n");
break;
}
}
int main (int argc, char *argv[]) {
char my_string[sizeof(int)] = "hi";
clever_switch(my_string);
return 0;
}
…Which of course doesn't compile.
On my machine ((union my_union) { "hi" }).my_int
is 26984
while ((union my_union) { "no" }).my_int
is 28526
. However I cannot write these numbers myself, because they depend on the endianness of the machine (so apparently my machine is little-endian). But the compiler knows about the latter and knows exactly during compile time what number ((union my_union) { "no" }).my_int
is going to be.
The annoying thing is that I can already do it, but only using a very obscure (and slightly less efficient) syntax. The following example compiles just fine:
#include <stdio.h>
void clever_switch (const char * const my_input) {
#define TWO_LETTERS_UINT(FIRST_LETTER, SECOND_LETTER) ((unsigned int) ((FIRST_LETTER) << 8) | (SECOND_LETTER))
switch (TWO_LETTERS_UINT(my_input[0], my_input[1])) {
case TWO_LETTERS_UINT('h', 'i'):
printf("You said hi!\n");
break;
case TWO_LETTERS_UINT('n', 'o'):
printf("Why not?\n");
break;
}
#undef TWO_LETTERS_UINT
}
int main (int argc, char *argv[]) {
clever_switch("hi"); /* "You said hi!" */
clever_switch("no"); /* "Why not?" */
return 0;
}
So the question remains: does the C compiler (or the C Standard in this case) really need to be so dumb?