C 常数之间的算术运算
考虑这一准则C 常数之间的算术运算,c,c-preprocessor,compile-time-constant,C,C Preprocessor,Compile Time Constant,考虑这一准则 #define A 5 #define B 3 int difference = A - B; “difference”的值是在编译时硬编码为“2”,还是在运行时计算出来的?标准没有规定这类内容。它没有提到像这样的潜在优化(这是有充分理由的。标准定义语义,而不是实现) 为什么不看看编译器的反汇编呢?这将给你一个明确的答案 那我们就这么做吧 以下是VC++10的输出: #include <iostream> #define A 5 #define B 3 int
#define A 5
#define B 3
int difference = A - B;
“difference”的值是在编译时硬编码为“2”,还是在运行时计算出来的?标准没有规定这类内容。它没有提到像这样的潜在优化(这是有充分理由的。标准定义语义,而不是实现) 为什么不看看编译器的反汇编呢?这将给你一个明确的答案 那我们就这么做吧 以下是VC++10的输出:
#include <iostream>
#define A 5
#define B 3
int main() {
int x = A - B;
std::cout << x; // make sure the compiler doesn't toss it away
010A1000 mov ecx,dword ptr [__imp_std::cout (10A2048h)]
010A1006 push 2
010A1008 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (10A2044h)]
return 0;
010A100E xor eax,eax
#包括
#定义一个5
#定义B3
int main(){
int x=A-B;
std::cout宏A
和B
有点分散注意力。这是:
#define A 5
#define B 3
int difference = A - B;
与此完全相同:
int difference = 5 - 3;
那么让我们来讨论后者
5-3
是一个常量表达式,它是一个“可以在翻译过程中而不是运行时进行计算,因此可以在常量可能存在的任何位置使用”的表达式。它也是一个*整型常量表达式。例如,案例标签必须是整型常量表达式,因此您可以编写以下内容之一:
switch (foo) {
case 2: /* this is a constant */
...
}
或者这个:
switch (foo) {
case 5 - 3: /* this is a constant expression */
...
}
但请注意,该定义指出,它可以在翻译过程中进行计算,而不是必须进行计算。有些上下文需要常量表达式,在这些上下文中,表达式必须在编译时进行计算
但是假设difference
是在某个函数中声明的,则初始值设定项不是这些上下文之一
任何值得你付出代价的编译器(即使是免费的)将在编译时将5-3
减少到2
,并生成将值2
存储在difference
中的代码。但不需要这样做。C标准指定了程序的行为;它没有指定必须如何实现该行为。但可以安全地假设,无论您使用什么编译器,都可以sing将用2
替换5-3
即使你写:
int difference = 2;
switch (foo) {
case 5 - 3: /* ... */
case 2: /* ... */
}
编译器可以合法地生成代码,将值5
加载到寄存器中,从中减去3
,并将寄存器的内容存储到差异
。这是一件愚蠢的事情,但语言标准并不排除它
只要最终结果是difference
的值为2
,语言标准就不关心它是如何实现的
另一方面,如果你写:
int difference = 2;
switch (foo) {
case 5 - 3: /* ... */
case 2: /* ... */
}
然后,编译器必须计算结果,以便能够诊断错误(不能有两个大小写标签具有相同的值)
最后,如果在文件范围(在任何函数之外)定义difference
,则初始值必须是常量。但在这种情况下,真正的区别不是编译时是否计算5-3
,而是是否允许使用非常量表达式
参考:2011年C标准的最新草案是(大PDF);常量表达式在第6.6节中讨论。您如何区分两者之间的差异?C标准有一个“仿佛”"规则,这意味着,如果你不能区分,实现可以随心所欲。分解代码,就是这样。我可能不会使用编译器,它不会降低到2,我认为它是不可行的,除非它是唯一的方法,以C的目标,一个平台本身是绝对可行的。我知道从第一公顷。nd体验到编译器的免费版本没有。你必须购买优化版本才能获得编译时常量计算这样基本的东西。当时我通过enum
constant evaluation绕过了这个限制,但它对于任何规模的项目都是不可行的。检查由您的编译器将为您提供一个仅对该编译器具有决定性的答案(使用您使用的特定设置)@KeithThompson:任何像样的优化编译器都能做到这一点。我说过标准中没有规定,所以这显然适用于你的编译器。没错,我确实错过了C标记,但答案不会有任何不同。+1非常好,详细的答案。我考虑过深入研究……但后来我记得我在工作:D