Case switch: ошибка: метка case не сводится к целочисленной константе
int value;
const int signalmin = some_function();
switch(value)
{
case signalmin:
break;
}
Я прочитал значение some_function и использую это значение int для включения регистра. Компилятор C99 возвращает:
ошибка: метка регистра не сводится к целочисленной константе
Но я не могу использовать #define
потому что значение int читается перед выполнением переключателя.
Ответы
Ответ 1
switch
метки должны быть постоянными выражениями, их нужно оценивать во время компиляции. Если вы хотите разветвляться на значения времени выполнения, вы должны использовать if
.
A const
-qualified variable не является константным выражением, это просто значение, которое вам не разрешено изменять.
Форма целочисленных константных выражений подробно описана в 6.6 (6) [C99 и черновик стандарта n1570 стандарта C2011]:
6 Целочисленное константное выражение должно иметь целочисленный тип и должно иметь только операнды которые являются целыми константами, константами перечисления, символьными константами, sizeof
выражения, результаты которых представляют собой целые константы, выражения _Alignof
и плавающие константы, которые являются непосредственными операндами приведения. Операторы Cast в целочисленной константе выражение должно преобразовывать только арифметические типы в целые типы, за исключением как части операнд к оператору sizeof
или _Alignof
.
Ограничение того, что только выражения sizeof
, результат которых является целочисленной константой, разрешают исключать выражения sizeof
, операнд которых является массивом переменной длины.
Ответ 2
Позвольте мне включить пример. Следующее было протестировано в версии gcc 4.6.3
с флагами -std=c99 -pedantic
:
#define SOME_HARDCODED_CONSTANT 0 //good
int foo(int i, int b){
const int c=0; //bad
int a=0; //bad
switch(i){
case c: //compile error
case a: //compile error.
case (b+a): //compile error
case SOME_HARDCODED_CONSTANT: //all good
case 5: //all good
}
}
Как отмечали другие, аргументы case
не могут быть оценены во время выполнения. Для этого используйте блок if-else
.
Ответ 3
В C. Все метки case
должны быть константами времени компиляции. В C квалификатор const
не создает константу времени компиляции, он просто обозначает, что переменная времени выполнения доступна только для чтения.
A switch
не является подходящей структурой управления для того, что вы пытаетесь сделать.
Ответ 4
В C переменные не должны использоваться в ярлыках case switch, а константные выражения разрешены там.
Ответ 5
В OSX, clang, кажется, воспринимает константы как ярлыки case без жалоб.
#include <stdio.h>
#define SOME_HARDCODED_CONSTANT 0 //good for sure
int foo(int i, int b){
const int c=1; //no problem!!!
switch(i){
case SOME_HARDCODED_CONSTANT: //all good
printf("case SOME_HARDCODED_CONSTANT\n"); break;
case c: //no compile error for clang
printf("case c\n"); break;
case 5: //all good
printf("case 5\n"); break;
}
return i+b;
}
int main() {
printf("test foo(1,3): %d\n", foo(1,3));
}
Вывод:
$> cc test.c -o test; ./test
case c
test foo(1,3): 4