且构网

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

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

更新时间:2022-06-13 07:53:52

您可以使用任何需要常量积分表达式然后将被优化的表达式.

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.