java未定义变量_(为什么)使用未初始化的变量未定义行为?

本文探讨了C标准中编译器优化如何影响未初始化变量的行为,特别是对于Java未定义变量的情况。通过示例代码解释,说明了编译器可能会如何处理未初始化的变量,甚至在某些情况下,优化可能导致意外的结果。讨论了编译器如何进行寄存器分配,并解释了在特定情况下,未初始化的变量可能导致未定义的行为。
摘要由CSDN通过智能技术生成

C标准为编译器提供了很大的优势来执行优化 . 如果您假设一个简单的程序模型,其中未初始化的内存设置为某个随机位模式,并且所有操作都按照它们的写入顺序执行,那么这些优化的后果可能会令人惊讶 .

注意:以下示例仅有效,因为 x 从未获取其地址,因此它是“类似寄存器” . 如果 x 的类型具有陷阱表示,它们也将是有效的;这对于无符号类型来说很少见(它需要“浪费”至少一点存储空间,并且必须记录在案),而且 unsigned char 是不可能的 . 如果 x 具有签名类型,则实现可以将位模式定义为 - (2n-1-1)和2n-1-1之间的数字作为陷阱表示 . 见Jens Gustedt's answer .

编译器尝试将寄存器分配给变量,因为寄存器比内存快 . 由于程序可能使用比处理器具有寄存器更多的变量,因此编译器执行寄存器分配,这导致在不同时间使用相同寄存器的不同变量 . 考虑程序片段

unsigned x, y, z; /* 0 */

y = 0; /* 1 */

z = 4; /* 2 */

x = - x; /* 3 */

y = y + z; /* 4 */

x = y + 1; /* 5 */

当评估第3行时, x 尚未初始化,因此(编译器的原因)第3行必须是某种可能足够明智的侥幸 . 由于在第4行之后未使用 z ,并且在第5行之前未使用 x ,因此可以对两个变量使用相同的寄存器 . 所以这个小程序编译成寄存器上的以下操作:

r1 = 0;

r0 = 4;

r0 = - r0;

r1 += r0;

r0 = r1;

x 的最终值是 r0 的最终值, y 的最终值是 r1 的最终值 . 如果 x 已正确初始化,则这些值为x = -3和y = -4,而不是5和4 .

有关更详细的示例,请考虑以下代码片段:

unsigned i, x;

for (i = 0; i < 10; i++) {

x = (condition() ? some_value() : -x);

}

假设编译器检测到 condition 没有副作用 . 由于 condition 不修改 x ,编译器知道第一次运行循环因为它尚未初始化,所以无法访问 x . 因此,循环体的第一次执行相当于 x = some_value() ,写入了's no need to test the condition. The compiler may compile this code as if you'

unsigned i, x;

i = 0; /* if some_value() uses i */

x = some_value();

for (i = 1; i < 10; i++) {

x = (condition() ? some_value() : -x);

}

这可以在编译器内部建模的方式是考虑任何取决于 x 的值,只要 x 未初始化,任何值都很方便 . 因为未初始化变量未定义时的行为,而不是仅具有未指定值的变量,编译器不需要跟踪任何方便值之间的任何特殊数学关系 . 因此编译器可以用这种方式分析上面的代码:

在第一次循环迭代期间, x 在评估 -x 时未初始化 .

-x 具有未定义的行为,因此它的值是任何方便的 .

优化规则 condition ? value : value 适用,因此此代码可简化为 condition; value .

当遇到问题中的代码时,同一个编译器会分析当 x = - x 被评估时, -x 的值是方便的 . 因此,可以优化分配 .

我没有找到一个行为如上所述的编译器的例子,但它是优秀的编译器试图做的优化 . 遇到一个我不会感到惊讶 . 这是程序崩溃的编译器的一个不太合理的例子 . (如果在某种高级调试模式下编译程序,可能不会令人难以置信 . )

这个假设的编译器将每个变量映射到不同的内存页面并设置页面属性,以便从未初始化的变量读取会导致调用调试器的处理器陷阱 . 首先对变量赋值,确保其内存页面正常映射 . 这个编译器在调试模式下没有't try to perform any advanced optimization — it',旨在轻松定位诸如未初始化变量之类的错误 . 当评估 x = - x 时,右侧会导致陷阱并且调试器将启动 .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值