【发布时间】:2025-12-13 21:00:01
【问题描述】:
我正在寻找一种方法来#define 一个宏,该宏将其参数强制为编译时常量,同时可以在表达式中使用。该方法应该在 C90 下工作并且向上兼容 - 如果可能的话,也可以移植到不同的 C++ 变体。此外,内存占用空间为 0 也是可取的。
以编译时最小宏为例。行为应该是:
#define CT_MIN(CTC_A, CTC B) <<<MAGIC>>>
int a = 1;
int b = a + CT_MIN(1,4); /* OK */
int c = a + CT_MIN(a,4); /* COMPILER DIAGNOSTIC */
为了引发编译诊断,一般来说,我可以模拟一个静态断言,如下所示:
typedef char ct_check_is_ct_constant[(CTC_A != 0) + 1];
如果 CTC_A 使用编译时间常数(数字)以外的任何内容,则不会编译(或至少会引发一些诊断);但如果 CTC_A 是一个数字,它总是会成功(考虑到范围)。 但是这个断言只能在多语句宏中工作,因此不能用作表达式的一部分。
我猜是这样的:
#define CT_MIN(CTC_A, CTC_B) \
( <expr check CTC_A>, \
<expr check CTC_B>, \
(CTC_A) < (CTC_B))? (CTC_A) : (CTC_B) \
)
但我不知道表达式必须是什么样子,以及是否存在这种情况。
有什么想法吗?
背景:
我通过定制的标题从不太可靠的来源获得了大量常量。这些常量强烈地参数化了我的代码。我想在预处理器和编译时为此常量实现零占用检查,以检查我的假设、环境和我编写正确代码生成器的技能。
【问题讨论】:
-
注意 VLA 类型。我认为您可能能够定义一个带有位域的结构类型,其大小是根据宏参数定义的,尽管我不相信自己会意识到所有警告并完全正确。
-
@user2357112 :-) 我不完全确定如何使用 VLA 类型来实现 MIN 宏,如果它的参数不是编译时常量,它将在编译时失败。
-
我的意思是确保您不会意外声明一个认为数组长度始终是编译时常量的 VLA 类型。
-
啊,我明白了。谢谢。我并不完全了解 VLA 功能(仍然以某种方式坚持使用 C89)。除了答案之外,您能否提供一个不会成为 VLA 的静态断言?
-
必须是标准C89?例如,gcc 的扩展可以让您实现这一目标。
标签: c macros c89 static-assert compile-time-constant