奇怪的 LLVM 在 For 循环中无符号到有符号的转换

Weird LLVM Unsigned to Signed Conversion in For Loop

本文关键字:无符号 符号 转换 循环 LLVM For      更新时间:2023-10-16

我不确定这是否只发生在Apple的LLVM Compiler 4.0(XCode 4.4.1)上,但我注意到以下行为:

NSUInteger currentIndex = 0;
NSUInteger sideSize = 2;
// Method A
for (NSInteger i = currentIndex-sideSize; i < currentIndex+sideSize; i++)
{
    printf("In the loopn"); // WON'T be executed
}
// Method B
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < currentIndex+sideSize; i++)
{
    printf("In the loopn"); // WON'T be executed
}
// Method C
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < (NSInteger)(currentIndex+sideSize); i++)
{
    printf("In the loopn"); // WILL be executed
}
// Method D
NSInteger initialIndex = currentIndex-sideSize;
NSInteger finalIndex = currentIndex+sideSize;
for (NSInteger i = initialIndex; i < finalIndex; i++)
{
    printf("In the loopn"); // WILL be executed
}
方法

B 和方法 C 几乎相同,只是我们没有将加法运算符的结果显式转换为有符号值。

谁能解释一下发生了什么?

问题是,如果在表达式中有有符号和无符号操作数,根据 C 标准,有符号操作数将被提升为无符号整数。然后发生的情况是,如果你从 0 中减去 2,则得到 -2,但由于它被视为无符号整数(在比较值时),它会溢出并最终成为某个大数字。这就是为什么方法 B 中的循环不执行而方法 C 中的循环执行的原因(当您显式将结果和/或操作数强制转换为 signed 时,不会发生溢出,并且循环正确从 -2 变为 2)。

这在C标准中是一件奇怪的事情,而不是在LLVM中。LLVM完全遵循这里的标准。