36 Stimmen

Warum kein Schalter an Zeigern?

Zum Beispiel:

#include <stdio.h>

void why_cant_we_switch_him(void *ptr)
{
    switch (ptr) {
        case NULL:
            printf("NULL!\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    void *foo = "toast";
    why_cant_we_switch_him(foo);
    return 0;
}

gcc test.c -o test
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values

Ich bin nur neugierig. Ist dies eine technische Einschränkung?

EDIT

Die Leute scheinen zu glauben, dass es nur einen konstanten Zeigerausdruck gibt. Ist das aber wirklich so? Hier ist zum Beispiel ein gängiges Paradigma in Objective-C (es ist wirklich nur C, abgesehen von NSString , id y nil die nur ein Hinweis sind, so dass sie immer noch relevant sind - ich wollte nur darauf hinweisen, dass es es Das ist zwar nur eine technische Frage, aber sie wird häufig verwendet):

#include <stdio.h>
#include <Foundation/Foundation.h>

static NSString * const kMyConstantObject = @"Foo";

void why_cant_we_switch_him(id ptr)
{
    switch (ptr) {
        case kMyConstantObject: // (Note that we are comparing pointers, not string values.)
            printf("We found him!\n");
            break;
        case nil:
            printf("He appears to be nil (or NULL, whichever you prefer).\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    NSString *foo = @"toast";
    why_cant_we_switch_him(foo);
    foo = kMyConstantObject;
    why_cant_we_switch_him(foo);

    return 0;
}

gcc test.c -o test -framework Foundation
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values

Es scheint, dass der Grund dafür ist, dass switch nur ganzzahlige Werte zulässt (wie die Compilerwarnung sagte). Ich nehme an, eine bessere Frage wäre, warum dies der Fall ist? (obwohl es jetzt wahrscheinlich zu spät ist.)

16voto

Tarydon Punkte 4969

Ein Schalter vergleicht die Variable mit einer Reihe von Kompilierzeit Konstanten. Außer null kann ich keine gültigen Kompilierzeitkonstanten sehen, mit denen man einen Zeiger vergleichen könnte. Zum Beispiel:

switch (ptr) { 
   case &var1: printf ("Pointing to var1"); break;
   case &var2: printf ("Pointing to var2"); break;
}

var1 und var2 sind wahrscheinlich in jedem Durchlauf des Programms unterschiedlich und wären keine Kompilierzeitkonstanten. Eine Möglichkeit wäre, dass es sich um Adressen von Ports handelt, die dem Speicher zugeordnet sind und die immer fest sind, aber ansonsten sehe ich nicht, wie man das aus den beiden Fällen (null/nicht-null) einfach erweitern könnte.

13voto

DigitalRoss Punkte 138823

Da es nur einen Ausdruck für einen konstanten Zeiger gibt

Da nur ein einziger konstanter Zeigerausdruck existiert, wird die switch Anweisung hat für Zeigerausdrücke wenig zu bieten. Sie haben im Wesentlichen die einzig mögliche Konstruktion angeführt.

12voto

Jeff Kelley Punkte 18810

Switch-Anweisungen wirken nur auf ganzzahlige Werte. Deshalb lautet die Fehlermeldung "switch quantity not an integer". Ich glaube nicht, dass es sich dabei um eine technische Einschränkung handelt, sondern dass es außerhalb der Sprachsyntax liegt.

8voto

Brian R. Bondy Punkte 325712

switch Anweisungen wirken nur auf ganzzahlige Ausdrücke. Ein Zeiger ist kein ganzzahliger Ausdruck.

Man kann einen Zeiger explizit in einen Integraltyp umwandeln, wenn man das möchte, aber der vorgeschlagene Code ist ein wenig seltsam und unnatürlich.

Um also Ihre Frage genau zu beantworten: Weil es keine implizite Konvertierung zwischen einem Zeiger und einem Integraltyp gibt.

5voto

Clifford Punkte 82130

Sie können (wenn Sie wirklich müssen). Setzen Sie den Zeiger einfach auf einen angemessen dimensioniert Ganzzahlig. Für diese intptr_t verwendet werden sollte. Das heißt nicht, dass ich es empfehlen würde, aber Sie werden Ihre Gründe haben.

#include <stdint.h>
#include <stdio.h>

void we_can_switch_him(void *ptr)
{
    switch ((intptr_t)ptr) {
        case (intptr_t)NULL:
            printf("NULL!\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    void *foo = "toast";
    we_can_switch_him(foo);
    return 0;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X