什么是C和C++中的未定义行为(UB)?那么未指定的行为和实现定义的行为呢?他们之间有什么区别?
发布于 2015-04-16 03:32:59
从历史上看,实现定义的行为和未定义的行为都代表了一种情况,在这种情况下,标准的作者期望编写高质量实现的人会使用判断来决定哪些行为保证(如果有的话)对在预期目标上运行的预期应用程序字段中的程序有用。高端数字编译代码的需求与低级系统代码的需求有很大的不同,UB和IDB都为编译器编写人员提供了满足这些不同需求的灵活性。两个类别都没有要求实现的行为方式对任何特定目的,甚至任何目的都是有用的。然而,声称适合某一特定目的的高质量实现应该以一种适合这种目的的方式运行,无论标准是否需要它。
实现定义的行为和未定义的行为之间唯一的区别是,前者要求实现定义和记录一致的行为,即使在实现可能做不到的情况下也是如此。它们之间的分界线不是实现定义行为通常是否有用(编译器编写人员应该在实际情况下定义有用的行为,无论标准是否要求它们),而是是否可能存在定义行为的同时代价高昂和无用的实现。这种实现可能存在的判断在任何方面、形状或形式上都不意味着对支持在其他平台上定义的行为的有用性的任何判断。
不幸的是,自20世纪90年代中期以来,编译器作者开始将缺乏行为授权解释为一种判断,即行为保障甚至在至关重要的应用领域,甚至在几乎不需要任何成本的系统中,也不值得付出代价。编译器编写人员没有将UB视为行使合理判断的邀请,而是开始将其作为不这样做的借口。
例如,给定以下代码:
int scaled_velocity(int v, unsigned char pow)
{
if (v > 250)
v = 250;
if (v < -250)
v = -250;
return v << pow;
}
两个补码的实现不需要花费任何的精力来将v << pow
作为两个补码的转换来处理,而不考虑v
是正的还是负的。
然而,今天的一些编译器作者偏爱的哲学是,因为只有当程序进行未定义的行为时,v
才可能是负面的,因此没有理由让程序剪切v
的负面范围。尽管过去每一个具有重要意义的编译器都支持负值的左移,而且大量现有代码依赖于这种行为,但现代哲学会解释这样一个事实,即标准认为左移负值是UB,这意味着编译器编写人员应该自由地忽略这一点。
https://stackoverflow.com/questions/2397984
复制相似问题