简体   繁体   中英

Checking types of macro parameters at compile time

To check that two variables have the same structure type I use a macro

#define assert_same_struct_types(a, b)    ((void) (sizeof((a)=(b))))

If some function-like macro

#define m(a,b) blablabla

assumes a and b should be of the same structure type, I add a compile time check:

#define m(a,b) (assert_same_struct_types(a, b), blablabla)

which provokes compiler error if caller of m(a,b) accidentally passes to m different types of structs.

However, this approach doesn't always work for builtin and pointer types due to implicit conversions between them.

So, is it possible to solve this problem for arbitrary types, not necessarily structs?

I need a solution for C89, however, it would be interesting to hear about C99 or C11 possibilities.

#define ASSERT_SAME_TYPE(a, b)  ((void) (&(a) == &(b)))

will get you a compile diagnostic and an error with -Werror (for gcc or a similar option for other compilers).

Note that a lot of compilers have a non standard extension typeof operator to get the type of an object and this can be used to check two types are the same.

This questions asks about a C89 solution, so far I didn't find a good way to do this, so instead of relying on C89, you can check if the compiler supports typeof and use it when available. Its not ideal but means as long as some developers use GCC/Clang/IntelC, the error gets caught. of course, if you tell your compiler only to support C89 this isn't going to help.

It gives better type checking but obviously fails to be of any use at all when not supported.

#ifdef __GNUC__
#define CHECK_TYPE(var, type)  {  \
    typeof(var) *__tmp;           \
    __tmp = (type *)NULL;         \
    (void)__tmp;                  \
} (void)0

#define CHECK_TYPE_PAIR(var_a, var_b)  {  \
    typeof(var_a) *__tmp;                 \
    __tmp = (typeof(var_b) *)NULL;        \
    (void)__tmp;                          \
} (void)0

#define CHECK_TYPE_PAIR_INLINE(var_a, var_b)  ((void)({  \
    typeof(var_a) *__tmp;                                \
    __tmp = (typeof(var_b) *)NULL;                       \
    (void)__tmp;                                         \
}))

#else
#  define CHECK_TYPE(var, type)
#  define CHECK_TYPE_PAIR(var_a, var_b)
#  define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (void)0
#endif

/* inline type checking - can mix in with other macros more easily using the comma operator,
 * C11 gives best results here */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#  define CHECK_TYPE_INLINE(val, type) \
    (void)((void)(((type)0) != (0 ? (val) : ((type)0))), \
           _Generic((val), type: 0, const type: 0))
#else
#  define CHECK_TYPE_INLINE(val, type) \
    ((void)(((type)0) != (0 ? (val) : ((type)0))))
#endif

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM