在C中编译时检查类型是结构还是指针?

k1t*_*ish 2 c c-preprocessor

注意:这不是由Paul T链接的问题的副本,因为我在询问是否有可能在编译时确定某个类型是否具有某种更广泛的不完整类型/种类,而不是在编译时是否已注册符号时间.这似乎是对这个问题的根本误解.

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

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

  • 能够在编译时检测类型是否是指针.(不,"使用_Generic测试你是否从减法中得到ptrdiff_t"技巧将不起作用,因为结构是可能的,你不能减去结构.)

  • 能够在编译时检测类型是否是结构.(如果这是可能的,那么如果检测到类型不是结构,则可以使用前面提到的_Generic技巧.)

我已经尝试了所有我能想到的关于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));
Run Code Online (Sandbox Code Playgroud)

不应该抛出任何错误.

Gun*_*ulz 5

完整答案(如果使用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
Run Code Online (Sandbox Code Playgroud)

因为在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
Run Code Online (Sandbox Code Playgroud)

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