switch case: error: case label wird nicht auf eine ganzzahlige Konstante reduziert
Lesezeit: 7 Minuten
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.
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
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
14056900cookie-checkswitch case: error: case label wird nicht auf eine ganzzahlige Konstante reduziertyes