关于未定义行为
|
通常,UB被认为是必须避免的事情,当前的C标准本身在附录J中列出了很多示例。
但是,在某些情况下,除了牺牲可移植性外,在使用UB方面我看不出任何危害。
考虑以下定义:
int a = INT_MAX + 1;
计算该表达式将导致UB。但是,如果我的程序打算在具有模块化算法的32位CPU上运行,该算法代表Two's Complement中的值,我倾向于相信我可以预测结果。
在我看来,UB有时只是C标准告诉我的方式:“我希望您知道自己在做什么,因为我们无法保证会发生什么。”
因此,我的问题是:即使C标准认为它依赖于调用UB,有时还是依赖于机器相关的行为是安全的,还是不管情况如何,都必须避免使用“ UB”?
没有找到相关结果
已邀请:
7 个回复
炉挤仙挟
不能保证是
。此行为启用对某些代码很重要的某些优化类别。 例如,知道未定义
可以将optimizing5ѭ优化为
。知道乘法“不能”溢出(因为这样做是不确定的)可以将
优化为
。尽管这些看起来微不足道,但通常通过内联和宏扩展来暴露这些事情。允许的一个更重要的优化是针对这样的ѭ9like循环:
在此循环中,如果未在溢出时定义
,则编译器可以假定该循环将精确地迭代
次,这允许进行广泛的循环优化。另一方面,如果定义了变量以在溢出时回绕,则编译器必须假定循环可能是无限的(如果
是
,则会发生这种情况)-然后禁用这些重要的循环优化。这特别影响64位平台,因为太多代码使用ѭ1作为归纳变量。
混侩闯空坷
)。例如,该循环
据说依赖于您的“与机器有关”的有符号整数类型的溢出行为。但是,在严格的溢出语义规则下,GCC编译器可以(并且会假设)递增
变量只会使其变大,而永远不会变小。这个假设将使GCC优化算法并生成无尽的循环
因为这是未定义行为的完全有效表现。 基本上,没有C语言中的“与机器有关的行为”之类的东西。所有行为都由实现决定,实现的级别是您所能达到的最低级别。实现将您与原始计算机隔离开来,并完美地隔离了您。除非实现明确允许您这样做,否则无法突破这种隔离并进入实际的原始计算机。通常,带符号整数溢出不是允许您访问原始计算机的那些上下文之一。
淘圃跺枯替
钨蜡唤喉晤
/
机制来阻止编译,以防使用其他编译器。
豹芜澈
懊毁暗
容淑阔九