I was looking at some preprocessor macros used in OpenSSL, and I came across the following from 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)))
I'm guessing its written that way to work around a compiler bug (probably something ancient that hasn't been supported in over a decade by the vendor).
What is the purpose of using the 1
above since its always true?
The conditional operator "&&" first evaluates whether its first operand (i.e., number % 2 == 0) is true and then evaluates whether its second operand (i.e., number % 4 == 0) is true. As both are true, the logical AND condition is true.
The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.
In computer programming, ?: is a ternary operator that is part of the syntax for basic conditional expressions in several programming languages. It is commonly referred to as the conditional operator, inline if (iif), or ternary if.
It's code that double checks if the correct type is passed. The pointer p is passed and along the type of that pointer must be also manually typed in the macro.
The ternary expression will always return the second operand but both second and third operands will be checked if their type matches, and if they don't you should get a compiler error.
A simple example:
int* p = NULL ; 1 ? p : ( float* )p ; //error 1 ? p : ( int* )p ; //ok
It's a static assertion about the function type before the cast, providing a type-safe cast.
From C11 (n1570) 6.5.15 (from the constraints section)
Conditional operator
(3) One of the following shall hold for the second and third operands:
- [omitted non-pointer stuff]
- both operands are pointers to qualified or unqualified versions of compatible types;
- one operand is a pointer and the other is a null pointer constant; or
- one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of
void
.
The third operand is a pointer to a function (so the last bullet never applies), so this compiles (without a warning) only if either p
is a null pointer constant or of a type compatible with void (*)(type)
for the last macro (after conversion to a function pointer, if p
is a function designator).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With