switch case: case label does not reduce to an integer constant

mad*_*phy 3 c switch-statement

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;

}
Run Code Online (Sandbox Code Playgroud)

And of course…

error: case label does not reduce to an integer constant
  case ((struct my_struct) { 4 }).my_int:
Run Code Online (Sandbox Code Playgroud)

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:

error: case label does not reduce to an integer constant
  case ((struct my_struct) { 4 }).my_int:
Run Code Online (Sandbox Code Playgroud)

…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>

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;

}
Run Code Online (Sandbox Code Playgroud)

So the question remains: does the C compiler (or the C Standard in this case) really need to be so dumb?

VHS*_*VHS 5

尽管表达式((struct my_struct) { 4 }).my_int确实在运行时评估为4,但它不是常数。开关盒需要一个常量表达式。

我看到您已声明my_intconst。但这仅意味着以后不能对其进行修改。这并不意味着表达式((struct my_struct) { 4 }).my_int是常量。

如果您使用if-statement代替switch-case,则可以。

if (((struct my_struct) { 4 }).my_int == 4) {
    printf("Hey there!\n");
}
Run Code Online (Sandbox Code Playgroud)

  • @VHS我只是在挑剔你的措辞。OP的代码在C标准的所有版本中都是无效的,但这不是因为`(((struct my_struct){4})。my_int`不是常量。它是一个常量[expression],但不是一个整数常量expression_,它是常量表达式的受限子类别。大小写标签不仅需要是常量,还需要是整数常量表达式。 (2认同)