Switch statements in C: variable in case?

2020-03-14 03:09发布

问题:

#include <stdio.h>
int main(int argc, char *argv[]){
    char a = 'c';
    switch('c'){
        case a:
            printf("hi\n");
    }
    return 0;
}

The above won't compile for this error:

case label does not reduce to an integer constant

Why is this not allowed?

回答1:

The compiler is explicitly allowed to use an efficient binary tree or a jump table to evaluate case statements.

For this reason, case statements are compile time constants.



回答2:

Think about, what if you had the following:

int a = 1, b = 1, c = 1;

switch (a)
{
case b: return 1;
case c: return 2;
}

What would it return?

The case labels need to be constant so that the compiler can prove that there are no ambiguities.



回答3:

The idea of a switch statement is that the compiler can produce code that only inspects the switch expression at run time and by that deduces the location to jump to.

If the case label could be expressions that are not constant, it would have to evaluate all such case expressions to see if there is one that matches. So instead of evaluating one expression, it would have to evaluate n expressions, where n is the number of case labels for that switch.

The whole idea of the switch is to do it the other way round than you did. Put the varying expression a in the switch itself, and put constants such as your 'c' in the case.



回答4:

The C99 standard says this (and the C89 standard was very similar):

§6.8.4.2 The switch statement

Constraints

¶1 The controlling expression of a switch statement shall have integer type.

[...]

¶3 The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion. There may be at most one default label in a switch statement.

That's the language requirement: case labels shall be integer constant expressions, and all the cases in a single switch shall be unique. That is the way C was designed. It is very unlikely to change now (even though the change would not break any currently valid code, or even change its meaning).