我无法想象编译器在没有左值时会做什么,例如:number>>1; 我的直觉告诉我,由于优化,编译器将从编译中丢弃这一行,如果优化被删除,会发生什么?它是否使用寄存器来进行操作?还是它的行为就像是函数调用一样,因此参数被传递到堆栈,并且使用的内存被标记为已释放?还是将其转换为 NOP 操作?我可以看到使用 VS++ 调试器发生了什么吗?感谢您的帮助。
2 回答
在您给出的示例中,它丢弃了该操作。它知道操作没有副作用,因此不需要发出代码来执行语句以生成正确的程序。如果禁用优化,编译器可能仍会发出代码。如果启用优化,编译器也可能会发出代码——它并不完美。
/FAsc
您可以使用Microsoft 编译器的命令行选项查看编译器发出的代码。该选项创建一个列表文件,其中包含编译器的目标代码输出和相关的源代码。
您也可以在调试器中使用“查看反汇编”来查看编译器生成的代码。
使用“查看反汇编”或/FAsc
优化代码,我希望不会看到编译器发出的代码。
假设这number
是一个整数类型的常规变量(not volatile
),那么任何有能力的优化编译器(Microsoft、Intel、GNU、IBM 等)都将生成 NOTHING。不是 a nop
,不使用寄存器等。
如果优化被禁用(在“调试构建”中),那么编译器很可能会“按照你的要求做”,因为它没有意识到它没有代码的副作用。在这种情况下,该值将被加载到寄存器中,并右移一次。结果不会存储在任何地方。编译器将执行“无用代码消除”作为优化步骤之一——我不确定是哪一个,但是对于这种相对简单的事情,我希望编译器能够通过相当基本的优化设置来解决。在某些情况下,涉及循环等,编译器可能不会优化代码,直到启用一些更高级的优化设置。
如评论中所述,如果变量是易失性的,则必须读取所代表的内存number
,因为编译器必须读取volatile
内存。
在 Visual Studio 中,如果您“查看反汇编”,它应该向您显示编译器生成的代码。
最后,如果这是 C++,也有可能变量不是常规整数类型,operator>>
当编译器看到这段代码时正在调用函数——这个函数除了返回结果之外可能有副作用,所以可能必须执行。但在 C 语言中情况并非如此,因为没有运算符重载。