5
y=x++;

它在编译器级别中断了多少步而不在 CPU 级别或指令上进行优化?是否创建了任何临时以将 x 分配给 y 或者直接发生?

4

6 回答 6

15

C++ 遵循 as-if 原则,所以答案确实是“n”步。

  • 它可能是2 : 1) 分配xy. 2) 增量x
  • 如果从不使用它可能是1y
  • 它可能是未定义的行为y被声明为int& y = x;
  • 最终产生相同结果的可能是100 次分配和重新分配。
于 2012-10-30T10:44:19.147 回答
8
  1. 一个临时变量是用值创建的== x
  2. x递增
  3. (保留在该临时变量中)的旧值x分配给y

这些将是基本步骤。

取决于你所说的“原始”是什么意思——如果你指的是 CPU 指令,那么答案会有所不同。

您可能想阅读有关后缀和前缀递增/递减运算符的更多信息。

于 2012-10-30T10:41:01.653 回答
2

这取决于您编译此代码的架构。

C++ 没有指定这些内容,甚至没有指定可能的“原始步骤”是什么。

对于古老的M68000 CPU ,一个可能的答案可能是:

move.l x, d0
addq.l #1, x
move.l d0, y

因此,这使用了三个指令(原始步骤)和一个临时的寄存器形式d0

注意:自从我编写 M68k 程序集以来已经有一段时间了,我确实希望上面的代码是有效的,但目前似乎在到达相关参考页面时遇到了问题。作为一个例子,我很确定它是有效的。

于 2012-10-30T10:40:41.480 回答
2

取决于原始步骤是什么意思,如果原始步骤是 CPU 指令,我做了如下快速测试:

(linux 环境,g++ 4.6.3)使用 g++ -S main.cpp 显示 g++ 生成了哪些 CPU 指令,我得到以下输出:

movl -8(%ebp), %eax<br>
movl %eax, -4(%ebp)<br>
addl $1, -8(%ebp)

这意味着 g++ 会将 y 复制到 x,然后增加 x。在这种情况下,会生成 3 个 CPU 指令(如果您将它们视为原始步骤)。

请注意,不同的编译器优化级别和不同的 CPU 架构,结果会有所不同。

于 2012-10-30T11:09:07.133 回答
1

请参阅运算符优先级表

步骤如下:

  • 一个临时变量被分配了x' 值。

  • x递增 1。

  • y分配有临时变量值。

因此,抽象级别的 3 个原始步骤。

于 2012-10-30T10:43:23.377 回答
0
  • 为 x 的地址分配寄存器
  • x的加载地址
  • 为 x 分配临时寄存器
  • 取消引用 x
  • 为 y 分配寄存器
  • 分配 y<=x
  • 增加 x
  • 写回 x
  • 为 y 的地址分配临时寄存器
  • y的加载地址
  • 商店 y

然后经过很多优化阶段后,它可能会使用两条指令进行处理:

add r0, r1, #0
add r1, r1, #1

感谢您的评论——无论如何,我的观点是编译器可能需要执行一些步骤来读取变量。(它是全局的还是在本地堆栈帧中,或者它是否具有链接器文件给出的绝对地址......)

编辑:当然这不是故事的结局:x 和 y 是什么类型的变量?它们是否比机器寄存器宽度长?它们是否更短并且需要零或符号扩展?也许它们是浮点数或双精度数,需要调用外部库...

于 2012-10-30T10:44:08.673 回答