Say that in existing source code, you happened upon the construct below:



#define CHECKED_TYPE(original_type, p) ((conversion_type*) (1 ? p : (original_type*) 0))

What might the purpose of this strange construct be?

At run-time, the inner conditional expression always evaluates to p , and thus the entire expression evaluates to the conversion to conversion_type* of p . Thus, with regard to what it evaluates to, the macro might as well have been written (conversion_type*) p .

At compile-time, however, a C11 compiler will apply the rules prescribed by the standard for the conditional expression:

6.5.15 Conditional operator Syntax 1 conditional-expression: … logical-OR-expression ? expression : conditional-expression … 3 One of the following shall hold for the second and third operands:

— both operands have arithmetic type;

— both operands have the same structure or union type;

— both operands have void type;

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

Because the macro hard-codes an expression with type original_type* , cases 1, 2, 3 will never apply. In practice neither the type pointed by p nor original_type is void , so the sixth case does not apply either. That leaves only cases 4 and 5: the pointer p must have compatible types up to qualifiers, or p must be a null pointer constant.

Clause 6.5.15:3 above falls below a Constraints section, which means that a compliant compiler has to emit a diagnostic if a C program doesn’t respect the stated conditions. Thus the macro CHECKED_TYPE(original_type, p) expands to something that causes at least a compiler warning if p is not of a type compatible up to qualifiers with original_type* , or a null pointer constant (e.g. NULL , 0 , (void*)0 ).

In short, the macro CHECKED_TYPE(original_type, p) checks that the pointer p has type original_type* before converting it to the hard-coded type conversion_type* . If the check fails, compilation will likely stop (depending on the compiler, but a compliant compiler has to at least emit a warning). Clang uses an enabled-by-default warning:

$ cat t.c #define CHECKED_TYPE(original_type, p) \ ((void*) (1 ? p : (original_type*) 0)) int main(void) { int x = 1; void *p = CHECKED_TYPE(int, &x); char y = 2; void *q = CHECKED_TYPE(int, &y); float z = 3; void *r = CHECKED_TYPE(int, &z); } $ clang t.c t.c:8:13: warning: pointer type mismatch ('char *' and 'int *') [-Wpointer-type-mismatch] void *q = CHECKED_TYPE(int, &y); ^~~~~~~~~~~~~~~~~~~~~ t.c:2:15: note: expanded from macro 'CHECKED_TYPE' ((void*) (1 ? p : (original_type*) 0)) ^ ~~~~~~~~~~~~~~~~~~ t.c:10:13: warning: pointer type mismatch ('float *' and 'int *') [-Wpointer-type-mismatch] void *r = CHECKED_TYPE(int, &z); ^~~~~~~~~~~~~~~~~~~~~ t.c:2:15: note: expanded from macro 'CHECKED_TYPE' ((void*) (1 ? p : (original_type*) 0)) ^ ~~~~~~~~~~~~~~~~~~ 2 warnings generated.

In real software, this idiom is found in OpenSSL’s source code.