已签名至未签名的转换

可能重复:
一个谜语(在C中)

看到这段代码

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) int array[] = {23,34,12,17,204,99,16}; int main() { int d; for(d=-1;d <= TOTAL_ELEMENTS-2;d++) printf("%d\n",array[d+1]); return 0; } 

现在这个循环不会运行。 sizeof()将返回无符号值,因此TOTAL_ELEMENTS具有无符号值。 现在,来到for循环,请告诉我,如果一元运算符’ – ‘在signed int 2上工作或隐式转换发生在unsigned中,然后’ – ‘运算符工作。

在您的示例中, d在比较中转换为unsigned int 。 但-1不能表示为unsigned int值,因此它被转换为UINT_ MAX。 要避免此行为,可以通过prepending (int)将比较的右侧转换为signed int

有关C中整数转换的详细信息,请参阅了解整数转换规则 。

d <= TOTAL_ELEMENTS-2中没有一元运算符。

TOTAL_ELEMENTS-2简化为二进制运算符为 – 的表达式。 然后该表达式变为无符号,因为其操作数之一是无符号的。

在d <= TOTAL_ELEMENTS-2的情况下,由于相同的原因,d's类型也被转换为unsigned int。

该标准的相关部分是第6.3.1.8#1节(ISO / IEC 9899:1999),其中说:

“否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则带有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型。”

是的,由于促销, d在该表达式中也有一个无符号类型,这就是循环失败的原因。

但问题是C编译器是否“认为”:

(unsigned) ((unsigned) 5 - (unsigned) 2)

即将2推广为未签名,或:

(unsigned) ((unsigned) 5 - (signed) 2)

即减法取两种类型的操作数。 当然,这没关系,因为两者的操作都是一样的。 但是,重点是减法将返回一种类型的值,因此理论上它只能接受该类型的参数。 所以它是第一个(unsigned int 2)。

PS(-2)是一元的,而(5-2)是二元的。

我怀疑无符号类型的sizeof()传播到表达式TOTAL_ELEMENTS-2 ,然后传播到d <= TOTAL_ELEMENTS-2两个操作数。 在TOTAL_ELEMENTS之前插入(int) TOTAL_ELEMENTS解决问题。

看,’ – ‘运算符是一元的是一个愚蠢的事情。忘了它。它是二进制’ – ‘,我意识到。

当2转换为无符号整数时,它变为无符号2,因此TOTAL_ELEMENTS-2的值等于无符号5,然后当d转换为无符号整数时,它得到一个大的正值,
所以循环失败了。

这是发生在这里?

是的,我没有写这个代码,这是我在网上找到的一些谜题。 谢谢你们所有人。