在下面显示的代码中,没有输出任何内容,这意味着for循环中的条件失败。可能的原因是什么?
我想知道,因为当我单独打印TOTAL_ELEMENTS时,它给出了5,所以这自然是5-2=3 => -1<=3,所以它应该打印一些东西。
#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;
}有人能解释一下这段代码吗?
发布于 2016-08-19 22:41:21
这是“通常的算术转换”的结果。
摘自C standard的6.3.1.8节
如果两个操作数具有相同的类型,则不需要进一步转换。
否则,如果两个操作数都具有带符号整数类型或都具有无符号整数类型,则具有较小整数转换秩的类型的操作数将转换为具有较大秩的操作数的类型。
否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则将具有带符号整数类型的操作数转换为具有无符号整数类型的操作数的类型。
否则,如果带符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数被转换为具有有符号整数类型的操作数类型。否则,这两个操作数都将转换为与带符号整数类型的操作数的类型相对应的无符号整数类型。
sizeof操作符返回一个size_t,它是一个无符号值。所以(sizeof(array) / sizeof(array[0])) - 2也是未签名的。
因为要比较有符号的值和无符号的值,所以有符号的值将转换为无符号的值。将-1转换为unsigned会产生最大的无符号值,从而导致比较结果为false。
如果您将右侧转换为int,它将按预期工作。
for(d=-1;d <= (int)(TOTAL_ELEMENTS-2);d++)输出:
23
34
12
17
204
99
16或者,您可以通过规范化索引数组的方式来避免这个问题:
for (d = 0; d < TOTAL_ELEMENTS; d++) {
printf("%d\n", array[d]);
}发布于 2016-08-19 22:45:11
当我尝试像这样打印TOTAL_ELEMENTS - 2时:
printf("total %d\n", TOTAL_ELEMENTS - 2);我得到了一个警告(使用gcc 4.8)说:
test.c:8:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("total %d\n", TOTAL_ELEMENTS - 2);
^该警告意味着TOTAL_ELEMENTS - 2为long unsigned。现在,当您将signed int与unsigned int进行比较时,有符号的整数将被视为无符号的。因此在d <= (TOTAL_ELEMENTS-2)中,d变成了一个非常高的正数(假设使用的是2的补数系统)。
您可以将结果强制转换为int以解决此问题。
d <= (int)(TOTAL_ELEMENTS-2)
或者,如果您在许多地方使用宏,则可以像这样进行更改:
#define TOTAL_ELEMENTS (int)(sizeof(array) / sizeof(array[0]))发布于 2016-08-19 22:55:42
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))它的计算结果为unsigned类型。然而,在您的循环中,d是一个signed值。在有符号值和无符号值的表达式中,有符号值被转换为无符号值。但是d是-1,它不适合无符号的值,所以它“环绕”到机器上的最高无符号值(在2的补码上)。
https://stackoverflow.com/questions/39041684
复制相似问题