我看了this很好太宽了问题,遇到一些UB我以前都不知道。有没有规则可以发现UB?
UB我不时看到的主要原因是在两个序列点之间改变两次变量。诸如:x = x++
或z = y++ + ++y;
。读取在两个序列点之间两次更改变量是UB帮助我了解这些情况下的根本原因。
但是,像负位移位这样的事情呢? (int x = 8 << -1
)有没有一个规则可以解释或者我应该记住这是一个独特的UB可能性?
我看了here和部分整数溢出我发现带负片的位移是写的,但我不明白他们为什么相关。当int
被移位太多时,会引起溢出,但IMO发生负移位仅仅是UB,并且问题不在于“超出边缘”的位...
也看了这里,没有回答我的问题:
对每个操作数执行整数升级。结果的类型是提升的左操作数的类型。如果右操作数的值为负或者大于或等于提升的左操作数的宽度,则行为未定义。
所以我的问题是:
- 具体而言,位移位与底片考虑整数溢出,如果是这样,为什么?
- 如果不是,它是更大现象的一部分吗?
- 是否存在(其他)不能归类于一个基本原因下的独特个案?
负移位未定义,移位过长(对于N位整数类型移位N位或更多位)也是如此。该标准如此说。你必须知道它是这样说的。是的,有很多情况,将它们分组会很棘手。 C11标准的附录J.2在第557-571页上记录了未定义的行为(每个结束页面只有几行,因此它多于14页)。定期阅读以了解未定义的内容。没有;我还没有记住它。 –
@JonathanLeffler这是一个令人印象深刻的名单,thx!尽管我希望有更容易记住的东西:) – CIsForCookies
回答你的部分 - *我希望更容易记住的东西*我的一般经验法则是 - 任何似乎改变不同实现(目标,平台等)行为的东西是一个红旗“点”UB。然后我确认清单。这很有意义,因为标准是在抽象机器上定义的,而不是任何实现。因此触摸实现的方面必须保持未定义。警惕实施定义的行为。 –