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.)

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

2voto

Dan Olson Punkte 21991

case Labels erwarten einen konstanten Ausdruck, in der Regel eine ganze Zahl, und Zeiger sind in der Regel nicht gut mit diesen zu vergleichen, außer im Fall von NULL. Sie könnten cast to intptr_t, aber es ist immer noch unsinnig, wenn Sie nur eine Sache haben, die Sie gegen vergleichen können.

switch Anweisungen existieren, weil der Compiler sie oft in eine Sprungtabelle ist ein Konzept, das am besten funktioniert, wenn es sich bei den Fallbezeichnungen um aufeinanderfolgende ganze Zahlen handelt. Aber im Falle eines Zeigers, der in einen ganzzahligen Typ umgewandelt wurde, gewinnen Sie nichts gegenüber einer if / else durch Verwendung von switch, nur mit einer umständlicheren Syntax.

1voto

Otávio Décio Punkte 72052

Es kann damit zusammenhängen, wie switch implementiert ist - es scheint höchstens eine ganze Zahl zu erwarten, so dass es ein bestimmtes CPU-Register verwenden kann, was mit einem Zeiger nicht möglich wäre.

0voto

Michael Cloud Punkte 11

Die Antwort, die den Nagel auf den Kopf trifft, liegt darin, dass Switch-Anweisungen zur Kompilierzeit mit anderen Daten verglichen werden müssen. Wenn man das mit Laufzeitdaten machen könnte, sehe ich jede Menge Gründe, das zu tun. Insbesondere, wenn ich herausfinden möchte, auf welche Funktion mein Funktionszeiger zeigt. Die Switch-Konstruktion ist viel eleganter als eine Reihe von if then else if-Anweisungen.

-1voto

DeveloperChris Punkte 3292

Doh! Warum überhaupt eine switch-Anweisung verwenden? switch-Anweisungen sollten nur verwendet werden, wenn Sie 3 oder mehr Optionen zur Auswahl haben, wenn Sie 2 Optionen haben, dann verwenden Sie eine if(){} else {}-Anweisung.

joshua dies ist keine legitime Verwendung eines Zeigers in einem Schalter.

Wenn Sie wirklich eine switch-Anweisung verwenden müssen, dann casten Sie sie in einen _int64 oder long long oder einen ganzzahligen Typ, der garantiert so groß wie oder größer als ein Zeiger ist (hängt vom Compiler ab).

Auch einige Compiler können die maximale Größe eines Schalters auf einen int oder eine andere beliebige Größe begrenzen. in diesem Fall können Sie eine switch-Anweisung überhaupt nicht verwenden.

DC

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