是或不是“常量表达式”的例子在C语言中?
即使在谷歌搜索了很多之后,我还是对 C 中的常量表达式和不是常量表达式感到有点困惑。您能否提供一个 C 语言中常量表达式和非常量表达式的示例?
I'm a tad confused between what is and is not a Constant Expression in C, even after much Googleing. Could you provide an example of something which is, and which is not, a Constant Expression in C?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
常量表达式可以在编译时求值。这意味着它没有变量。例如:
是一个常量表达式。类似:
不是,假设
someNumber
是一个变量(即,它本身不是一个编译时常量)。A constant expression can be evaluated at compile time. That means it has no variables in it. For example:
is a constant expression. Something like:
is not, assuming
someNumber
is a variable (ie, not itself a compile-time constant).常量表达式还有另一个微妙之处。有些事情编译器知道,但预处理器无法知道。
例如,
(24*60*60)
可以由两者计算,但sizeof struct foo
只有编译器知道。如果您尝试验证struct
的定义是否满足外部规定的大小,或其成员是否映射到外部指定的偏移量,则这种区别可能很重要。 (在编写设备驱动程序时,经常会出现这种用例,其中struct
描述设备寄存器在内存空间中的布局。)在这种情况下,您不能简单地说
#if (sizeof(struct UART) = = 12)
因为预处理器在编译之前运行,根本无法知道任何类型的大小。然而,它是一个常量表达式,并且可以作为全局变量的初始值设定项(例如 int UARTwords = sizeof(struct UART) / sizeof(short);),或者声明一个数组(例如unsigned char UARTmirror[sizeof(struct UART)];
)There is another subtlety to constant expressions. There are some things that are known to the compiler, but cannot be known to the preprocessor.
For example
(24*60*60)
can be computed by both, butsizeof struct foo
is only known to the compiler. This distinction can matter if you are trying to verify that astruct
is defined to meet an externally mandated size, or that its members are mapped at externally specified offsets. (This use case often arises when coding device drivers where thestruct
describes device registers as layed out in memory space.)In that instance you cannot simply say
#if (sizeof(struct UART) == 12)
because the preprocessor operates at a pass ahead of the compilation and simply cannot know the size of any types. It is, however, a constant expression and would be valid as an initializer for a global variable (e.g.int UARTwords = sizeof(struct UART) / sizeof(short);
), or to declare the size of an array (e.g.unsigned char UARTmirror[sizeof(struct UART)];
)似乎没有人提到另一种常量表达式:地址常量。具有静态存储持续时间的对象的地址是一个地址常量,因此您可以在文件范围内执行此类操作:
字符串文字定义具有静态存储持续时间的数组,因此此规则也是您可以在文件范围内执行此操作的原因:
Nobody seems have mentioned yet another kind of constant expression: address constants. The address of an object with static storage duration is an address constant, hence you can do this kind of thing at file scope:
String literals define arrays with static storage duration, so this rule is also why you can do this at file scope:
任何单值文字都是常量表达式。
(字符串文字很奇怪,因为它们实际上是数组。似乎
"hello"
并不是真正的常量,因为它最终必须链接等等,并且地址和内容可以改变应用于常量或类型的大多数运算符(sizeof、强制类型转换等)都是常量表达式。
任何仅涉及常量表达式的表达式本身也是常量表达式。
任何涉及函数调用或非常量表达式的表达式通常都不是常量表达式。
任何宏作为常量表达式的状态取决于它扩展的内容。
我最初在这里有一些关于 const 标识符的内容,但我测试了它,显然它不适用于 C。 奇怪的是,const 没有声明常量(至少,没有足够的“常量”足以在
switch
语句中使用)。然而,在 C++ 中却是这样。Any single-valued literal is a constant expression.
(String literals are weird, because they're actually arrays. Seems
"hello"
isn't really a constant, as it ends up having to be linked and all that, and the address and contents can change at runtime.)Most operators (sizeof, casts, etc) applied to constants or types are constant expressions.
Any expression involving only constant expressions is itself also a constant expression.
Any expression involving function calls or non-constant expressions is usually not a constant expression.
Any macro's status as a constant expression depends on what it expands to.
I originally had some stuff in here about
const
identifiers, but i tested that and apparently it doesn't apply in C.const
, oddly enough, doesn't declare constants (at least, not ones "constant" enough to be used inswitch
statements). In C++, however, it does.另一个有趣的小问题:在 C 中,“枚举”的值是一个常量,但只能在“枚举”声明完成后才能使用。例如,以下内容在标准 C 中是不可接受的,但在 C++ 中是可以接受的:
它可以重写:
尽管这最终会定义多个不同的枚举类型,而不是保存所有值的枚举类型。
Another fun little wrinkle: in C, the value of an 'enum' is a constant, but may only be used after the declaration of the 'enum' is complete. The following, for example, is not acceptable in standard C, though it is acceptable in C++:
It could be rewritten:
though this would end up defining multiple different enumeration types, rather than one which holds all the values.
此外,
'a'
或'\n'
等整数字符常量
也是编译器可识别的常量。它们的类型为int
。Also
integral character constants
as'a'
or'\n'
are constants that the compiler recognizes as such. They have typeint
.