switch case: error: case label wird nicht auf eine ganzzahlige Konstante reduziert

Lesezeit: 7 Minuten

Benutzeravatar von Jim Clermonts
Jim Clermonts

int value;

const int signalmin = some_function();

switch(value)
{
   case signalmin:
   break;
}

Ich lese den Wert von some_function und verwende diesen int-Wert, um einen Switch-Fall einzuschalten. Der C99-Compiler gibt zurück:

Fehler: Case-Label wird nicht auf eine Integer-Konstante reduziert

Aber ich kann a nicht verwenden #define da der int-Wert gelesen wird, bevor der Schalter ausgeführt wird.

Benutzeravatar von Daniel Fischer
Daniel Fischer

switch Etiketten müssen konstante Ausdrücke sein, sie müssen zur Kompilierzeit ausgewertet werden. Wenn Sie Laufzeitwerte verzweigen möchten, müssen Sie eine verwenden if.

EIN const-Qualifizierte Variable ist nicht a ständiger Ausdruckes ist lediglich ein Wert, den Sie nicht ändern dürfen.

Die Form von ganzzahligen konstanten Ausdrücken ist in 6.6 (6) detailliert beschrieben. [C99 and the n1570 draft of the C2011 standard]:

6 Ein ganzzahliger konstanter Ausdruck muss einen ganzzahligen Typ haben und darf nur Operanden haben, die ganzzahlige Konstanten, Aufzählungskonstanten, Zeichenkonstanten, sizeof
Ausdrücke, deren Ergebnisse ganzzahlige Konstanten sind, _Alignof Ausdrücke und Floating-Konstanten, die die unmittelbaren Operanden von Umwandlungen sind. Cast-Operatoren in einem ganzzahligen konstanten Ausdruck konvertieren nur arithmetische Typen in ganzzahlige Typen, außer als Teil eines Operanden für die sizeof oder _Alignof Operator.

Die Einschränkung, dass nur sizeof Ausdrücke, deren Ergebnis eine ganzzahlige Konstante ist, werden ausgeschlossen sizeof Ausdrücke, deren Operand ein Array variabler Länge ist.

  • Nun, ein const ist kein ganzzahliger konstanter Ausdruck, aber was ist mit static const ?

    – Cyan

    26. August 2015 um 16:54 Uhr

  • @Cyan Nicht in C (zuletzt habe ich nachgesehen). In anderen Sprachen mag das anders sein, .

    – Daniel Fischer

    26. August 2015 um 17:13 Uhr

  • Es ist erwähnenswert, dass in C++ const int foo = some_expr; macht foo ein konstanter Ausdruck genau dann, wenn some_expr ist ein konstanter Ausdruck. (Ich bin mir nicht 100% sicher, ob ich die Regel ganz richtig sage.) In C, const bedeutet lediglich schreibgeschützt.

    – Keith Thompson

    11. Juni 2019 um 1:52 Uhr

  • Ein weiterer Grenzfall: Funktionsadressen sind ganzzahlige Konstanten, aber da ihre Werte Adressen sind, die vom Linker und nicht vom Compiler bestimmt werden, können Sie einen Funktionszeiger nicht mit einem switch/case-Block vergleichen, selbst wenn er gecastet wird const unitptr_t. Dies gilt unabhängig davon, ob die Funktion ist static.

    – KrisW

    1. September um 11:56


Lassen Sie mich mit einem Beispiel eingreifen. Folgendes wurde in der gcc-Version getestet 4.6.3 mit den Fahnen -std=c99 -pedantic einstellen:

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

Wie andere angemerkt haben, case Argumente können zur Laufzeit nicht ausgewertet werden. Benutze ein if-else blockieren, um das zu tun.

  • Ganz klar die beste Antwort. Vielen Dank.

    – Noel

    4. Juli 2016 um 19:19 Uhr

  • Interessanter Fall (kein Wortspiel beabsichtigt): case (1 + 3): das ist alles gut (gcc 9 -Wall -Wextra -Werror -pedantic)

    – alx

    30. März 2020 um 19:15 Uhr


In C. alle case Etiketten müssen sein Kompilierzeit Konstanten. In C, die const Der Qualifizierer erstellt keine Konstante zur Kompilierzeit, sondern gibt lediglich an, dass eine Laufzeitvariable schreibgeschützt ist.

EIN switch ist nicht die geeignete Kontrollstruktur für das, was Sie versuchen zu tun.

In C dürfen in den Schalterfallbeschriftungen keine Variablen verwendet werden, stattdessen sind dort nur konstante Ausdrücke erlaubt.

Unter OSX scheint Clang Konstanten als Case-Labels ohne Beanstandungen zu akzeptieren.

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

Ausgabe:

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

  • Es beschwert sich, wenn Sie es darum bitten: caseconst.c:10:14: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]. Hier, const int c = 1; teilt dem Compiler den Wert (als ganzzahliger konstanter Ausdruck) zur Kompilierzeit mit, daher ist es ihm möglich, ihn zu behandeln c als wäre es ein ganzzahliger konstanter Ausdruck in der switch. Wenn Sie initialisieren c Erwarten Sie bei einem Funktionsaufruf einen Kompilierungsfehler.

    – Daniel Fischer

    4. Juni 2015 um 8:41 Uhr

  • Sie können eine andere Version verwenden. Mein cc beschwert sich über nichts und meldet Version wie folgt. $> cc –version $> Apple LLVM Version 6.0 (clang-600.0.57) (basierend auf LLVM 3.5svn) $> Ziel: x86_64-apple-darwin14.3.0

    – Farley

    6. Juni 2015 um 0:46 Uhr

  • Ja, eine andere Version. Wenn Sie jedoch verlangen, dass es wählerisch ist, muss es warnen, -std=c11 -Weverything muss dir auch davon erzählen -Wgnu-folding-constant, -pedantic-errors muss zu einem Kompilierfehler führen. Aber da es eine ziemlich harmlose Sache ist, müssen Sie dem Compiler sagen, dass er wirklich wählerisch sein soll, bevor er es erwähnt.

    – Daniel Fischer

    6. Juni 2015 um 10:51 Uhr

  • Das wählerische Ding ist nicht immer notwendig. Constant Folding/Propagation ist für einen anständigen Compiler von grundlegender Bedeutung, um herauszufinden, ob das Case-Label unabhängig von Deklarationen konstant ist oder nicht. In diesem Fall ist die Warnung bei expliziten konstanten Deklarationen standardmäßig nicht erforderlich, es sei denn, Benutzer fordern dies an.

    – Farley

    6. Juni 2015 um 16:24 Uhr

  • Ja, deshalb beschwert sich der Compiler nur, wenn Sie ihn darum bitten. Mein Punkt ist, dass es nach dem Sprachstandard kein gültiger Code ist und der Compiler daher eine Diagnosemeldung ausgeben muss (beim Kompilieren im kompatiblen Modus), selbst wenn er den Code akzeptiert (an dem nichts auszusetzen ist). Und es ist gut, den Compiler wählerisch sein zu lassen, da dies Aufschluss über nicht-portablen Code gibt und Sie eine fundierte Entscheidung treffen können, ob Sie den Code unverändert lassen oder ihn portabel umschreiben.

    – Daniel Fischer

    6. Juni 2015 um 17:40 Uhr

Benutzeravatar von Purushottam Rawat
Purushottam roh

Ich verwende diesen folgenden Code und er funktioniert einwandfrei

Fall “+”: dh mit doppelten Anführungszeichen erhalte ich einen Fehler, also versuchen Sie zu schreiben

case ‘+’: in einfachen Anführungszeichen

#include <stdio.h>

int main() {
    // Write C code here
    char x;
    int a=20,b=10;
    scanf("%c",&x);
    switch(x)
    {
        
    case '+':
            printf("%d",a+b);
            break;
    case '-':
            printf("%d",a-b);
            break;
    case '*':
            printf("%d",a*b);
            break;
    case "https://stackoverflow.com/":
            printf("%d",a/b);
            break;
    default:
            printf("sorry");
    }
    
    return 0;
}

  • Es beschwert sich, wenn Sie es darum bitten: caseconst.c:10:14: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]. Hier, const int c = 1; teilt dem Compiler den Wert (als ganzzahliger konstanter Ausdruck) zur Kompilierzeit mit, daher ist es ihm möglich, ihn zu behandeln c als wäre es ein ganzzahliger konstanter Ausdruck in der switch. Wenn Sie initialisieren c Erwarten Sie bei einem Funktionsaufruf einen Kompilierungsfehler.

    – Daniel Fischer

    4. Juni 2015 um 8:41 Uhr

  • Sie können eine andere Version verwenden. Mein cc beschwert sich über nichts und meldet Version wie folgt. $> cc –version $> Apple LLVM Version 6.0 (clang-600.0.57) (basierend auf LLVM 3.5svn) $> Ziel: x86_64-apple-darwin14.3.0

    – Farley

    6. Juni 2015 um 0:46 Uhr

  • Ja, eine andere Version. Wenn Sie jedoch verlangen, dass es wählerisch ist, muss es warnen, -std=c11 -Weverything muss dir auch davon erzählen -Wgnu-folding-constant, -pedantic-errors muss zu einem Kompilierfehler führen. Aber da es eine ziemlich harmlose Sache ist, müssen Sie dem Compiler sagen, dass er wirklich wählerisch sein soll, bevor er es erwähnt.

    – Daniel Fischer

    6. Juni 2015 um 10:51 Uhr

  • Das wählerische Ding ist nicht immer notwendig. Constant Folding/Propagation ist für einen anständigen Compiler von grundlegender Bedeutung, um herauszufinden, ob das Case-Label unabhängig von Deklarationen konstant ist oder nicht. In diesem Fall ist die Warnung bei expliziten konstanten Deklarationen standardmäßig nicht erforderlich, es sei denn, Benutzer fordern dies an.

    – Farley

    6. Juni 2015 um 16:24 Uhr

  • Ja, deshalb beschwert sich der Compiler nur, wenn Sie ihn darum bitten. Mein Punkt ist, dass es nach dem Sprachstandard kein gültiger Code ist und der Compiler daher eine Diagnosemeldung ausgeben muss (beim Kompilieren im kompatiblen Modus), selbst wenn er den Code akzeptiert (an dem nichts auszusetzen ist). Und es ist gut, den Compiler wählerisch sein zu lassen, da dies Aufschluss über nicht-portablen Code gibt und Sie eine fundierte Entscheidung treffen können, ob Sie den Code unverändert lassen oder ihn portabel umschreiben.

    – Daniel Fischer

    6. Juni 2015 um 17:40 Uhr

1405690cookie-checkswitch case: error: case label wird nicht auf eine ganzzahlige Konstante reduziert

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy