c - 开关盒 : case label does not reduce to an integer constant

标签 c switch-statement

我非常清楚 switch 语句背后的机制以及为什么需要整数常量。我不明白的是为什么下面的 case 标签不被认为是整数常量。之后怎么样了?一个不存在的变量?任何人都可以分类吗? C 编译器真的需要这么笨吗?

struct my_struct {
    const int my_int;
};

switch (4) {

case ((struct my_struct) { 4 }).my_int:

    printf("Hey there!\n");
    break;

}

当然……

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

编辑以回答 Eugene 的评论:

What's you real use case? If it is an integer constant, why to make it so complicated?

我试图找到一个巧妙的 hack 来在两个字符的字符串之间切换,使用 union 而不是 struct,如下例所示:

#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;

}

…这当然不能编译。

在我的机器上 ((union my_union) { "hi"}).my_int26984((union my_union) { "no"}).my_int28526。但是我不能自己写这些数字,因为它们取决于机器的字节序(所以显然我的机器是小字节序的)。但是编译器知道后者,并且在编译期间确切地知道 ((union my_union) { "no"}).my_int 将是什么数字。

烦人的是我可以已经做到了,但只是使用了一种非常晦涩(而且效率稍低)的语法。下面的例子编译得很好:

#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;

}

所以问题仍然存在:C 编译器(或本例中的 C 标准)真的需要这么笨吗?

最佳答案

虽然表达式 ((struct my_struct) { 4 }).my_int 在运行时确实被评估为 4,但它不是常量。 switch-case 需要一个常量表达式。

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

如果你使用 if-statement 而不是 switch-case,你会没事的。

if (((struct my_struct) { 4 }).my_int == 4) {
    printf("Hey there!\n");
}

关于c - 开关盒 : case label does not reduce to an integer constant,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55580175/

相关文章:

Java,奇怪的 switch 语句行为

c++ - GetSaveFileName/IFileSaveDialog - 用户输入事件/对文件名更改使用react?

c - GCC/SDL2 无限期挂起并停止响应

c++ - C/C++中的内存分配

c - OpenMP - 在包含并行 for 循环的并行区域中串行化 for 循环

c - C 中的进程间通信,一次一个字符

batch-file - 如何使用BATCH文件中的SWITCH解析命令行参数

在 C 中的 case/switch 语句中,无法重新启动到有限状态机中的初始情况

java - 当访问默认情况时如何重新启动此 switch 语句?

c++ - 我可以使用开关来保持功能吗?