Problem NULL Pointer in case Konstruktionen
-
Hallo Liebes Forum,
Ich soll eine Software compilieren. Leider bekomme ich die folgende
pointers are not permitted as case values
Ich habe das Problem auf den folgenden Quellcode reduziert:
#include <stdio.h> int main(int argc, char **argv) { int*test=NULL; switch(test) { case NULL:printf("is empty\n");break; default:printf("is not empty\n"); }; };
Dafür erhalte ich die Fehlermeldung vom gcc
test.c:5: error: switch quantity not an integer test.c:6: error: pointers are not permitted as case values
Weiß jemand von euch, warum das nicht geht? Vielen Dank im vorraus.
-
switch((ptrdiff_t)test) { case 0: printf("is empty\n"); break; ... ... ...
-
Werner12 schrieb:
Hallo Liebes Forum,
Weiß jemand von euch, warum das nicht geht? Vielen Dank im v******.
klar, siehe Fehlermeldung: pointers are not permitted as case values
wieso machst du nicht einfach
if(test == NULL) printf("is empty\n"); else printf("is not empty\n");
???
-
Weil das eigentliche Programm riesige switch-Blöcke enthält.
-
Werner12 schrieb:
Weil das eigentliche Programm riesige switch-Blöcke enthält.
und? ehrlich gesagt, ich verstehe deine Erklärung nicht.
-
den Block kannst du doch so behalten
du musst doch nur die Zeile mit der Bedingung ändernBsp.:
int i; /* ... */ switch(i) { case 1: /* 100 lines of code */ break; case 2: /* 250 lines of code */ break default: /* 150 lines of code */ break; }
das wären 508 Zeilen code, aber tatsächlich musst du nur 8 Zeilen verändern:
if(i == 1) { /* 100 lines of code */ } else if(i == 2) { /* 250 lines of code */ } else { /* 150 lines of code */ }
die änderung sollte wohl nicht soo lange dauern
-
Oder besser:
die riesigen Switch-Blöcke in eigene Funktionen auslagern. (Rest wie bereits erklärt)
-
was haben deine switchblöcke, welche den wert einer integer auswerten mit dem intergerzeiger zu tun...?
int *i=??????; printf("Pointer is %s\n", (i==NULL) ? "empty" : "valid"); switch(*i){ case 1: //.... break; case 2: //.... break; case 3: //.... break; default: //.... break; }
-
#include <stdio.h> int main(int argc, char **argv) { int*test=NULL; switch((int)test) { case (int)NULL:printf("is empty\n");break; default:printf("is not empty\n"); }; };
-
fricky schrieb:
switch((ptrdiff_t)test) { case 0: printf("is empty\n"); break; ... ... ...
Das ist keine gute Idee. Denn das funktioniert auch nur auf Systemen, wo der Nullzeiger tatsächlich dem Wert 0 entspricht.
-
groovemaster schrieb:
Denn das funktioniert auch nur auf Systemen, wo der Nullzeiger tatsächlich dem Wert 0 entspricht.
ISO/IEC 9899:1999 schrieb:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
-
fricky schrieb:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
Du hast nicht verstanden, was der Satz aussagt. Schau dir am besten mal an, was eine integer constant expression ist. Im Beispiel wird maximal eine integer constant expression mit dem Wert 0 in ptrdiff_t umgewandelt, aber nicht in einen Zeiger.
-
groovemaster schrieb:
Du hast nicht verstanden, was der Satz aussagt. Schau dir am besten mal an, was eine integer constant expression ist.
eine 0 z.b.
der satz sagt aus, dass 0 und )void*)0 das selbe sind, also eine nullpointer-konstante.if (irgendein_pointer == 0) { // passt immer, wenn man testen will, ob's ein nullpointer ist }
-
Also wirklich *-freak/frick ich mach das immer folgendermaßen:
> if(!ptr)
alles andere ist blasphemie
-
void* p = 0; // Nullpointer (initialisiert mit einem konstanten Ausdruck) intptr_t i = (intptr_t)p; assert( i == 0 ); // nicht zwingend erfüllt i = 0; p = (void*)i; // könnte in trap resultieren assert( p == 0 ); // nicht zwingend erfüllt
Glücklicherweise ist dies die einzige Stelle, bei der die Semantik davon abhängt, ob der initialisierende Ausdruck ein konstanter Ausdruck ist oder nicht.
kleine Anmerkung: die Konvertierung void* -> intptr_t -> void* ist in C nur mit void* reversibel (liefert den ursprünglichen Zeigerwert) - in C++ gilt dies für alle Zeigertypen
-
Bei deinem letzten assert sollte es nicht heißen
assert( p == NULL ); // nicht zwingend erfüllt
???
Zu deiner Anmerkung? Wieso in C nur mit void* reversibel? Wieso gilt das nicht zwingend bspweise mit int* ?
-
supertux schrieb:
Bei deinem letzten assert sollte es nicht heißen
assert( p == NULL ); // nicht zwingend erfüllt
Beides ist möglich, da auch ein einfaches 0 eine Nullpointerkonstante ist.
Zu deiner Anmerkung? Wieso in C nur mit void* reversibel? Wieso gilt das nicht zwingend bspweise mit int* ?
Weil der C-Standard diesbezüglich keine Aussage zu anderen Zeigertypen macht.
-
fricky schrieb:
eine 0 z.b.
der satz sagt aus, dass 0 und )void*)0 das selbe sind, also eine nullpointer-konstante.if (irgendein_pointer == 0) { // passt immer, wenn man testen will, ob's ein nullpointer ist }
Richtig, nur war das ja nicht das Thema. camper hat es schon geschrieben, es ging darum
(ptrdiff_t) 0 == (ptrdiff_t)(void*) 0
was nicht zwangsläufig wahr sein muss. Allerdings ist dies auf vielen Systemen trotzdem wahr, da der Nullzeiger eben dem Wert 0 entspricht, also alle Bits 0. Es geht nur darum, dass es für das eigentliche Problem bessere Lösungen gibt und das Brechen der Plattformunabhängigkeit an dieser Stelle absolut unnötig ist.
-
camper schrieb:
Zu deiner Anmerkung? Wieso in C nur mit void* reversibel? Wieso gilt das nicht zwingend bspweise mit int* ?
Weil der C-Standard diesbezüglich keine Aussage zu anderen Zeigertypen macht.
alles klar.
-
groovemaster schrieb:
es ging darum
(ptrdiff_t) 0 == (ptrdiff_t)(void*) 0
was nicht zwangsläufig wahr sein muss.
wenn, wie wir nun alle wissen, 0 == (void)0* wahr ist, dann kann der selbe cast auf beiden seiten, ob nun nach ptrdiff_t, char oder double, auch nichts dran ändrn. 0 bleibt 0, das ist nun mal so.