把自己放在编译器的位置。您正在实施 C 标准要求和保证的内容。
所以你编译代码,没有优化,得到这样的东西,逐行编译代码,没有任何分析:
- add stack space for `sum`
...
- initialize k to 0
beginning_of_for:
- if k < N is not met, goto after_for
- add w[k] to sum
- increment k
- goto beginning_of_for
after_for:
- ...
- (for example) print sum
它运行并且最初 sum 碰巧包含值 0。您看不到任何奇怪的行为,因为您很幸运(或者更不幸)。
现在他们告诉你,编译器,优化代码。您需要环顾四周并排除任何不必要的操作以节省尽可能多的时间和/或空间。你四处走动,发现 sum 未初始化。按照标准,这意味着您可以保证以后不会从该变量中读取(即使程序员证明已经这样做了,但您不在乎,因为标准说您不这样做需要照顾)。此外,如果您将一个未初始化的值添加到某个值,您会得到另一个未初始化的值,再次保证您不会稍后读取它。
所以这是你作为编译器的假设:
- variable X is defined but not initialized
- some operations that don't read from X
- operation that writes to X a value that is not uninitialized
- operations that read from X
从您的角度来看,在 X 使用不依赖于其他未初始化值的值初始化之前,从 X 读取的任何值都可以给出任意值,因此您可以只使用 0 而不是实际读取从那个值。更重要的是,任何基于未初始化值的写入都可以被丢弃,因为结果仍然是未初始化的值,因此它可以是任何值。
换句话说,您之前未优化的代码:
- add stack space for `sum`
...
- initialize k to 0
beginning_of_for:
- if k < N is not met, goto after_for
- add w[k] to sum
- increment k
- goto beginning_of_for
after_for:
- ...
- (for example) print sum
分析如下:
Pass 1:
- add stack space for `sum` [sum uninitialized]
...
- initialize k to 0 [keep this as is]
beginning_of_for:
- if k < N is not met, goto after_for [keep this as is]
- add w[k] to sum [remove this line: sum is still uninitialized]
- increment k [keep this as is]
- goto beginning_of_for [keep this as is]
after_for:
- ...
- (for example) print sum [use 0 or whatever instead of sum]
这给出了这个:
- add stack space for `sum`
...
- initialize k to 0
beginning_of_for:
- if k < N is not met, goto after_for
- increment k
- goto beginning_of_for
after_for:
- ...
- (for example) print whatever
下一轮优化如下:
Pass 2:
- add stack space for `sum` [sum uninitialized]
...
- initialize k to 0 [replace 0 with N because of (1)]
beginning_of_for:
- if k < N is not met, goto after_for [remove because of (1)]
- increment k [remove because of (1)]
- goto beginning_of_for [remove because of (1)]
after_for:
- ...
- (for example) print whatever [keep this as is]
(1) the for loop is empty. `k` is `int` so it is guaranteed it will not overflow
(Note: signed integer overflow is **undefined behavior** according to
the standard), so the loop terminates with a single side effect: `k` reaches
`N`. So there is no point in actually looping.
现在你的代码变成了:
- add stack space for `sum`
...
- initialize k to N
- ...
- (for example) print whatever
在最后一关,你会得到:
Pass 3:
- add stack space for `sum` [remove because sum is unused]
...
- initialize k to N [remove because k is unused]
- ...
- (for example) print whatever [keep this as is]
这意味着你最后剩下的是:
- (for example) print whatever
这就是优化如何导致你的整个代码因为未初始化的变量而被丢弃。