在编译时检查宏参数的类型

时间:2012-07-12 10:11:48

标签: c

要检查两个变量是否具有相同的结构类型,我使用宏

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

如果有一些类似函数的宏

#define m(a,b) blablabla

假设a和b应该是相同的结构类型,我添加一个编译时检查:

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

如果m(a,b)的调用者意外地传递给m种不同类型的结构,则会引发编译器错误。

但是,由于它们之间的隐式转换,这种方法并不总是适用于内置和指针类型。

那么,是否有可能为任意类型解决这个问题,而不一定是结构?

我需要C89的解决方案,但是,听听C99或C11的可能性会很有趣。

2 个答案:

答案 0 :(得分:3)

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

将使用-Werrorgcc或其他编译器的类似选项)为您提供编译诊断和错误。

请注意,许多编译器都有一个非标准的扩展typeof运算符来获取对象的类型,这可以用来检查两种类型是否相同。

答案 1 :(得分:1)

这个问题询问了C89解决方案,到目前为止我没有找到一个好方法,所以不用依赖C89,你可以检查编译器是否支持typeof并在可用时使用它。它并不理想,但只要一些开发人员使用GCC / Clang / IntelC就意味着错误被捕获。 当然,如果你告诉你的编译器只支持C89,这对你没有帮助。

它提供了更好的类型检查,但在不受支持的情况下显然完全无法使用。

#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