且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何检查参数是否是 C 预处理器宏中的整数常量表达式?

更新时间:2023-12-01 08:38:34

您可以使用任何需要常量整数表达式的表达式,然后将其优化出来.

You can use any expression that needs a constant integral expression and that will then be optimized out.

#define NPOT(X)                                         
 (1                                                     
 ? complex_algorithm(X)                                 
 : sizeof(struct { int needs_constant[1 ? 1 : (X)]; })  
 )

最终您应该将 sizeof 的结果转换为适当的整数类型,因此返回表达式是您期望的类型.

eventually you should cast the result of the sizeof to the appropriate integer type, so the return expression is of a type that you'd expect.

我在这里使用一个未标记的 struct

I am using an untagged struct here to

  • 有一个类型,所以真的不会产生临时的
  • 具有唯一的类型,这样表达式可以在代码中的任何位置重复而不会引起冲突
  • 触发使用 VLA,从 C99 开始,struct 内不允许使用 VLA:
  • have a type so really no temporary is produced
  • have a unique type such that the expression can be repeated anywhere in the code without causing conflicts
  • trigger the use of a VLA, which is not allowed inside a struct as of C99:

结构或联合的成员可以有任何对象类型,而不是可变修饰类型.

A member of a structure or union may have any object type other than a variably modified type.

我使用三元 ?:1 作为选择表达式,以确保始终根据其类型评估 :,但是从不作为表达式求值.

I am using the ternary ?: with 1 as the selecting expression to ensure that the : is always evaluated for its type, but never evaluated as an expression.

似乎 gcc 接受 struct 内的 VLA 作为扩展,甚至没有警告它,即使我明确地说 -std=c99.这对他们来说真是个坏主意.

It seems that gcc accepts VLA inside struct as an extension and doesn't even warn about it, even when I explicitly say -std=c99. This is really a bad idea of them.

对于这样一个奇怪的编译器 :) 你可以改用 sizeof((int[X]){ 0 }).这和上面的版本一样被禁止",但另外甚至 gcc 也抱怨它.

For such a weird compiler :) you could use sizeof((int[X]){ 0 }), instead. This is "as forbidden" as the above version, but additionally even gcc complains about it.