2012-12-28 2 views
26
int value; 

const int signalmin = some_function(); 

switch(value) 
{ 
    case signalmin: 
    break; 
} 

Odczytuję wartość some_function i używam tej wartości int, aby włączyć obudowę przełącznika. C99 kompilator daje powrotem:przypadek przełącznika: błąd: etykieta przypadku nie redukuje się do stałej całkowitej.

błąd: case etykieta nie zmniejsza liczbę całkowitą stałą

Ale nie mogę użyć #define ponieważ wartość int jest odczytywany przed przełącznik uruchamia.

Odpowiedz

37

switch Etykiety muszą być wyrażeniami stałymi, muszą być oceniane podczas kompilacji. Jeśli chcesz rozgałęzić w czasie wykonywania wartości, musisz użyć if.

A-const - zmienna kwalifikowana nie jest stałym ciągiem , jest to po prostu wartość, której nie wolno modyfikować.

Postać stałą całkowitą wyrażenia wyszczególniono 6,6 (6) [C99 oraz projekt n1570 standardu C2011]:

6 An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.

zastrzeżeniem, że tylko sizeof wyrażenia, których wynikiem jest stałą całkowitą wolno wykreśla wyrażenia sizeof, których operandem jest tablica o zmiennej długości.

+1

dzięki za jednoznaczną odpowiedź, będę użycie zamiast if. –

+0

Cóż, 'const' nie jest stałym wyrażeniem całkowitym, ale co z' statyczną const'? – Cyan

+0

@Cyan Nie w C (ostatnio wyglądałem). W innych językach rzeczy mogą się różnić,. –

5

W C. wszystkie znaki case muszą być czas kompilacji stałych. W języku C kwalifikator const nie tworzy stałej czasowej kompilacji, jedynie wyznacza, że ​​zmienna czasu wykonywania jest tylko do odczytu.

A switch nie jest odpowiednią strukturą kontrolną do tego, co próbujesz zrobić.

0

W języku C zmienne nie mogą być używane w etykietach znaczników przełączania, zamiast tego wyrażenia stałe są tam dozwolone.

5

Pozwól, że wpadnę z przykładem. Poniższa był testowany na gcc w wersji 4.6.3 flagami -std=c99 -pedantic zestawie:

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

jak inni to zauważyli, case argumenty nie mogą być oceniane w czasie wykonywania. Użyj bloku if-else, aby to zrobić.

+0

Najwyraźniej najlepsza odpowiedź. Dzięki. – Noel

0

W systemie OSX clang wydaje się przyjmować stałe jako etykiety na koperty bez skarg.

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

wyjściowa:

$> cc test.c -o test; ./test 
case c 
test foo(1,3): 4 
+0

Narzeka, jeśli poprosisz o to: 'caseconst.c: 10: 14: warning: expression nie jest stałym wyrażeniem całkowitym; składanie go do stałej to rozszerzenie GNU [-Wgnu-składanie-stała] '. W tym przypadku 'const int c = 1;' pozwala kompilatorowi poznać wartość (jako stałe wyrażenie całkowite) w czasie kompilacji, dlatego możliwe jest traktowanie 'c' tak, jakby było wyrażeniem stałym w postaci liczby całkowitej w' przełączniku ' '.Jeśli zainicjalizujesz 'c' z wywołaniem funkcji, spodziewaj się błędu kompilacji. –

+0

Możesz użyć innej wersji. Mój cc nie skarży się na nic i raportuje wersję w następujący sposób. $> cc --version $> Apple LLVM wersja 6.0 (clang-600.0.57) (na podstawie LLVM 3.5svn) $ Target: x86_64-apple-darwin14.3.0 – Farley

+0

Tak, inna wersja. Niemniej jednak, gdy zażądasz, aby był wybredny, musi ostrzec, '-std = c11 -Wszystko" musi ci o tym powiedzieć, także '-Wgnu-składanie-stałej',' -przeciwne-błędy' musi prowadzić do błędu kompilacji . Ale ponieważ jest to raczej nieszkodliwe, powinieneś powiedzieć kompilatorowi, że jest naprawdę wybredny, zanim o nim wspomni. –

Powiązane problemy