Bedingungsoperator mit konstantem (wahrem) Wert?

Lesezeit: 2 Minuten

Benutzer-Avatar
jww

Ich habe mir einige Präprozessor-Makros angesehen, die in OpenSSL verwendet werden, und bin auf Folgendes gestoßen crypto/stack/safestack.h:

#define CHECKED_STACK_OF(type, p) \
    ((_STACK*) (1 ? p : (STACK_OF(type)*)0))

#define CHECKED_SK_FREE_FUNC(type, p) \
    ((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))

#define CHECKED_SK_FREE_FUNC2(type, p) \
    ((void (*)(void *)) ((1 ? p : (void (*)(type))0)))

Ich schätze, es ist so geschrieben, um einen Compiler-Fehler zu umgehen (wahrscheinlich etwas Altes, das seit über einem Jahrzehnt nicht mehr vom Anbieter unterstützt wird).

Was ist der Zweck der Verwendung von 1 oben, da es immer wahr ist?

  • Überprüfung der Art von pwahrscheinlich – der zweite und der dritte Operand des Bedingungsoperators müssen in denselben Typ konvertierbar sein.

    – TC

    21. Dezember 2014 um 2:59 Uhr

Benutzer-Avatar
2501

Es ist Code, der doppelt überprüft, ob der richtige Typ übergeben wird. Der Zeiger p wird übergeben und der Typ dieses Zeigers muss auch manuell in das Makro eingegeben werden.

Der ternäre Ausdruck gibt immer den zweiten Operanden zurück, aber sowohl der zweite als auch der dritte Operand werden überprüft, ob ihr Typ übereinstimmt, und wenn dies nicht der Fall ist, sollten Sie einen Compilerfehler erhalten.

Ein einfaches Beispiel:

int* p = NULL ;

1 ? p : ( float* )p ;    //error

1 ? p : ( int* )p ;      //ok

Es ist eine statische Behauptung über den Funktionstyp vor der Umwandlung, die eine typsichere Umwandlung bereitstellt.

Ab C11 (n1570) 6.5.15 (aus dem Abschnitt Einschränkungen)

Bedingter Operator

(3) Für den zweiten und dritten Operanden gilt:

  • [omitted non-pointer stuff]
  • beide Operanden sind Zeiger auf qualifizierte oder nicht qualifizierte Versionen kompatibler Typen;
  • ein Operand ist ein Zeiger und der andere eine Nullzeigerkonstante; oder
  • Ein Operand ist ein Zeiger auf einen Objekttyp und der andere ein Zeiger auf eine qualifizierte oder nicht qualifizierte Version von void.

Der dritte Operand ist ein Zeiger auf eine Funktion (das letzte Aufzählungszeichen trifft also nie zu), daher wird dies (ohne Warnung) nur dann kompiliert, wenn beides der Fall ist p ist eine Nullzeigerkonstante oder von einem Typ, der mit kompatibel ist void (*)(type) für das letzte Makro (nach Umwandlung in einen Funktionszeiger, wenn p ist ein Funktionsbezeichner).

1363800cookie-checkBedingungsoperator mit konstantem (wahrem) Wert?

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

Privacy policy