Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
497 views
in Technique[技术] by (71.8m points)

c - Detecting Integer Constant Expressions in Macros

There was a discussion in the Linux kernel mailing list regarding a macro that tests whether its argument is an integer constant expression and is an integer constant expression itself.

One particularly clever approach that does not use builtins, proposed by Martin Uecker (taking inspiration from glibc's tgmath.h), is:

#define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))

This macro expands into an integer constant expression of value 1 if the argument is an integer constant expression, 0 otherwise. However, it relies on sizeof(void) to be allowed (and different than sizeof(int)), which is a GNU C extension.

Is it possible to write such a macro without builtins and without relying on language extensions? If yes, does it evaluate its argument?


For an explanation of the macro shown above, see instead: Linux Kernel's __is_constexpr Macro

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use the same idea, where the type of a ?: expression depends on whether an argument is a null pointer constant or an ordinary void *, but detect the type with _Generic:

#define ICE_P(x) _Generic((1? (void *) ((x)*0) : (int *) 0), int*: 1, void*: 0)

Demo on Ideone. _Generic is a C11 addition, so if you're stuck on C99 or something earlier, you won't be able to use it.

Also, have standard links for the definition of a null pointer constant and the way null pointer constants interact with the type of a ?: expression:

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

and

If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...