主要观点:实现一个宏,以(整数或浮点数)表达式为参数,验证表达式为常量表达式,否则中止编译,同时“返回”相同值且类型与原表达式相同,有多种方法可解决,取决于使用的 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) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。