c - 在 C 的编译时检查类型是结构还是指针?
问题描述
注意:这不是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));
不应该抛出任何错误。
解决方案
完整答案(如果使用 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/)
推荐阅读
- apache-spark - org.apache.spark.SparkException:通过spark将数据写入Hbase时写入行时任务失败
- php - 我下载的文件将其名称更改为“下载”,尽管我在标题中更改了它
- keyboard - 使用 python 访问应用程序
- javascript - javascript 错误:为什么我无法将标签从“li”克隆/复制到“table”?
- node.js - 使用 Sails.js 将多个文件上传到 Amazon S3 存储桶?
- node.js - 在 heroku nodejs 服务器准备好之前执行任务
- mongodb - 模拟来自 MongoDB 的数据以满足 Jest 中的 TypeScript
- log4j2 - 如何使用 log4j2 属性文件在每次运行时生成具有日期时间戳的日志文件
- xcode - 为后期处理设置 Facebook SDK 会导致控制台中出现错误消息
- php - Mysql查询以搜索四舍五入的浮点数