2014-12-21 17 views
28

szukałem w niektórych makr preprocesora użytych w OpenSSL, i natknąłem się na następujący od crypto/stack/safestack.h:Operator warunkowy o stałej (prawdziwej) wartości?

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

Zgaduję jego napisany w taki sposób, aby obejść błędu kompilatora (prawdopodobnie coś starożytnego że Hasn od dziesięciolecia był wspierany przez sprzedawcę).

Jaki jest cel używania powyższego 1, ponieważ jest zawsze prawdziwy?

+3

Weryfikacja typu 'p', prawdopodobnie - drugiego i trzeciego argumentu operatora warunkowego musi być możliwa do zamiany na ten sam typ. –

Odpowiedz

25

Jest to kod, który sprawdza, czy poprawny typ jest przekazywany. Wskaźnik p jest przekazywany i wzdłuż typu tego wskaźnika musi być również ręcznie wpisany w makrze.

Wyrażenie potrójne zawsze zwróci drugi operand, ale drugi i trzeci operand zostaną sprawdzone, jeśli ich typ się zgadza, a jeśli nie, powinieneś otrzymać błąd kompilatora.

Prosty przykład:

int* p = NULL ; 

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

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

Dziękuję bardzo. – jww

13

Jest to statyczne twierdzenie o rodzaju funkcję przed obsady, zapewniając bezpieczny typ obsady.

od C11 (n1570) 5.06.15 (z sekcji Ograniczenia)

operatora warunkowego

(3) jeden z poniższych czynności utrzymywania w drugiej i trzeciej wielkości:

  • [pominięto elementy niebędące wskaźnikiem]
  • oba operandy są wskaźnikami do kwalifikowanych lub niewykwalifikowanych wersji komp rodzaje atible;
  • jeden operand jest wskaźnikiem, a drugi stałą zerową; lub
  • jeden operand jest wskaźnikiem do typu obiektu, a drugi jest wskaźnikiem do kwalifikowanej lub niekwalifikowanej wersji void.

Trzeci argument jest wskaźnikiem do funkcji (tak ostatni pocisk nie dotyczy), więc to kompiluje (bez ostrzeżenia) tylko wtedy, gdy albo p jest zerowy wskaźnik stały lub typu zgodnego z void (*)(type) dla ostatniego makra (po konwersji na wskaźnik funkcji, jeśli oznaczenie funkcji to p).