首页 > 解决方案 > 在 C 的编译时检查类型是结构还是指针?

问题描述

注意:这不是Paul T 链接的问题的重复,因为我在问是否可以在编译时确定一个类型是否属于某个更广泛的不完整类型/种类,而不是在编译时是否已注册符号时间。这似乎是对这个问题的根本误解。

我正在用 C 编写一个库来处理伪泛型函数,这些函数通过宏包装器将类型作为参数。

为了节省细节(因为它们相当复杂),我认为有两个可能的功能可以提供帮助:

我已经在 Godbolt 上尝试了所有我能想到的东西(甚至尝试将类型与不完整的匿名结构进行比较并玩弄 __builtin_types_compatible_p),但找不到任何解决方案。

如果有人有任何解决方案,我很乐意看到它们,否则我可能最终不得不使设计变得有点复杂——所以如果不可能的话,这不是世界末日,但如果可以做到,那将是理想的。

大致了解其中一个宏的外观或其预期输出:

int *a;
assert(!IS_STRUCT(a));
assert(IS_POINTER(a));
struct {} b;
assert(IS_STRUCT(b));
assert(!IS_POINTER(b));

不应该抛出任何错误。

标签: cc-preprocessor

解决方案


完整答案(如果使用 EDG 前端):

如果您的 IDE / 编译器使用的是 EDG C++ 前端(很多都是),并且您使用的是C,而不是 C++(您的标签建议),并且您说您正在使用 typeof,那么您可以检测如下结构(参见最新手册,第 75 页):

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_STRUCT(expression_or_type_name) __is_class(typeof (expression_or_type_name)))
#endif

因为在C中 __is_class()仅适用于结构http://www.cplusplus.com/reference/type_traits/is_class/)。

此外,可以类似地检测指针,如下所示:

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_POINTER(expression_or_type_name) (__is_convertible_to(typeof (expression_or_type_name), void*) || __is_convertible_to(typeof (expression_or_type_name), void const*) || __is_convertible_to(typeof (expression_or_type_name), void volatile*) || __is_convertible_to(typeof (expression_or_type_name), void const volatile*))
#endif

http://www.cplusplus.com/reference/type_traits/is_convertible/


推荐阅读