dte*_*ech 12 c undefined undefined-behavior language-lawyer
根据这篇文章,不确定的价值是:
3.17.2
1 indeterminate value
either an unspecified value or a trap representation
Run Code Online (Sandbox Code Playgroud)
根据谷歌的说法,不确定性的定义是:
根据thefreedictionary,可确定的是:
根据merriam-webster,确定(在特定的上下文中)是:
因此,常识规定尽管在编译期间不确定值是未知的,但它在运行时是完全可确定的,例如,您总是可以读取占用该内存位置的任何事件.
还是我错了?如果是这样,为什么?
编辑:为了澄清,我发布了与用户试图说服不确定值不确定的用户之间的争论,我非常怀疑.
编辑2:澄清,通过"可确定的"我并不意味着稳定或可用的值,即使它是未初始化的内存的垃圾值,仍然可以确定该垃圾的价值.我的意思是,试图确定这个价值仍会产生一些价值,而不是......没有行动.所以这个值必须来自一些内存,分配为仍然不确定的值的存储,我高度怀疑编译器实际上会使用一个随机数生成器只是为了提出一些任意值.
AnT*_*AnT 17
它不确定的事实不仅意味着它在第一次读取时是不可预测的,它还意味着它不能保证稳定.这意味着两次读取相同的未初始化变量不能保证产生相同的值.因此,您无法通过阅读来"确定"该值.(参见DR#260,从2004年开始对该主题进行初步讨论,DR#451在2014年重申该位置.)
例如,a
可以指定变量来占用R1
具有特定时间帧(而不是存储器位置)的CPU寄存器.为了建立最佳的可变寄存器分配调度,"对象寿命"的语言级概念不够精确.CPU寄存器由优化编译器管理,基于更精确的"值寿命"概念.当变量被赋值为确定值时,值生存期开始.当最后一次读取先前分配的确定值时,值寿命结束.值生存期确定变量与特定CPU寄存器关联的时间范围.R1
b
.尝试a
在其值生命周期之外读取未初始化的变量实际上可能会导致读取变量b
,这可能是主动更改.
在此代码示例中
{
int i, j;
for (i = 0; i < 10; ++i)
printf("%d\n", j);
for (j = 0; j < 10; ++j)
printf("%d\n", 42);
}
Run Code Online (Sandbox Code Playgroud)
编译器可以很容易地确定,即使对象寿命i
和j
重叠,值寿命完全不重叠,这意味着两者i
并j
能得到分配到同一个CPU寄存器.如果发生类似的事情,您可能很容易发现第一个循环打印i
每次迭代的不断变化的值.这与j
不确定的价值观完全一致.
请注意,此优化不一定需要CPU寄存器.另一个例子,一个关注保留有价值的堆栈空间的智能优化编译器可能会分析上面代码示例中的值生存期并将其转换为
{
int i;
for (i = 0; i < 10; ++i)
printf("%d\n", <future location of j>);
}
{
int j;
for (j = 0; j < 10; ++j)
printf("%d\n", 42);
}
Run Code Online (Sandbox Code Playgroud)
使用变量i
并j
在不同时间占用内存中的相同位置.在这种情况下,第一个循环可能会再次打印i
每次迭代的值.
oua*_*uah 11
连续两次读取不确定值可以给出两个不同的值.此外,读取不确定的值会在陷阱表示的情况下调用未定义的行为.
在DR#260中,C委员会写道:
不确定的值可以由任何位模式表示.C标准规定不要求对代表给定值的位的两次检查将观察到相同的位模式,只是每次的观察模式将是该值的有效表示.
[...]在达到我们的响应时,我们注意到要求不确定值的不可变位模式会减少优化机会.例如,如果包含它们的内存被分页,则需要跟踪不确定值的实际位模式.这对优化程序来说似乎是一种不必要的限制,对程序员没有任何补偿性好处.
C90标准清楚地表明,从不确定的位置读取是不确定的行为.更新的标准不再那么清楚(不确定的内存是"未指定的值或陷阱表示"),但编译器仍然以一种只有在读取不确定的位置是未定义的行为时才可行的方式进行优化,例如,乘以未初始化变量中的整数乘以2会产生奇数结果.
所以,简而言之,不,你无法阅读任何占据不确定记忆的事情.
归档时间: |
|
查看次数: |
752 次 |
最近记录: |