主要观点:实现一个宏,以(整数或浮点数)表达式为参数,验证表达式为常量表达式,否则中止编译,同时“返回”相同值且类型与原表达式相同,有多种方法可解决,取决于使用的 C 标准和是否允许编译器扩展。
关键信息:
- 介绍了多种实现宏的方法,如
constexpr compound literals、__builtin_constant_p、static_assert、sizeof + compound literal with array type、sizeof + enum constant、Comma operator等。 - 各方法的优缺点,如
constexpr compound literals需 C23 且 Clang 不支持;__builtin_constant_p需 GNU 扩展;static_assert可能改变表达式类型,不支持浮点数等。 - 提到 GCC 的一些奇怪行为及解决办法。
重要细节: constexpr compound literals利用 C23 中的typeof和constexpr及指定复合字面量的存储持续时间来实现。__builtin_constant_p结合__builtin_choose_expr,在表达式为常量时选择原表达式,否则报错。static_assert通过sizeof和匿名struct魔法来确保表达式为静态,但其可能改变类型且对浮点数有限制。sizeof + compound literal with array type利用复合字面量数组类型验证表达式为常量,有一些限制。sizeof + enum constant用枚举常量代替复合字面量,但存在枚举“泄漏”等问题。Comma operator通过将sizeof放在单独表达式并用逗号运算符忽略来解决类型改变问题,可通过将sizeof结果转换为void消除警告。- 还提到了 GCC 的奇怪行为及解决办法,以及读者指出的使用
_Generic的解决方案等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。