在 C 语言中检测一个表达式是否为常量

主要观点:实现一个宏,以(整数或浮点数)表达式为参数,验证表达式为常量表达式,否则中止编译,同时“返回”相同值且类型与原表达式相同,有多种方法可解决,取决于使用的 C 标准和是否允许编译器扩展。
关键信息

  • 介绍了多种实现宏的方法,如constexpr compound literals__builtin_constant_pstatic_assertsizeof + compound literal with array typesizeof + enum constantComma operator等。
  • 各方法的优缺点,如constexpr compound literals需 C23 且 Clang 不支持;__builtin_constant_p需 GNU 扩展;static_assert可能改变表达式类型,不支持浮点数等。
  • 提到 GCC 的一些奇怪行为及解决办法。
    重要细节
  • constexpr compound literals利用 C23 中的typeofconstexpr及指定复合字面量的存储持续时间来实现。
  • __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的解决方案等。
阅读 10
0 条评论