在下面显示的代码中,没有任何内容被打印,这意味着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;
}
有人可以解释一下这段代码吗?
答案 0 :(得分:33)
这是&#34;通常的算术转换&#34;。
的结果来自C standard:
的第6.3.1.8节如果两个操作数具有相同的类型,则不再进一步转换 需要的。
否则,如果两个操作数都有有符号整数类型或两者都有 无符号整数类型,类型较小的操作数 整数转换等级转换为操作数的类型 排名更高。
否则,如果具有无符号整数类型的操作数具有 等级大于或等于另一个类型的等级 操作数,那么带有符号整数类型的操作数是 转换为带无符号整数的操作数类型 类型。
否则,如果带有符号整数类型的操作数的类型可以 表示带有unsigned的操作数类型的所有值 整数类型,那么带无符号整数类型的操作数是 转换为带有符号整数类型的操作数的类型。
否则,两个操作数都将转换为无符号 整数类型对应于带有signed的操作数的类型 整数类型。
sizeof
运算符返回size_t
,这是一个无符号值。所以(sizeof(array) / sizeof(array[0])) - 2
也是无符号的。
由于您要比较有符号值和无符号值,因此有符号值将转换为无符号值。将-1转换为无符号会导致最大的无符号值,从而导致比较为假。
如果您将右侧投向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]);
}
答案 1 :(得分:9)
当我尝试像这样打印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
进行比较时,该signed int将被视为无符号。因此,在d <= (TOTAL_ELEMENTS-2)
中,d
成为一个非常高值的正数(假设使用2的补数系统)。
您可以将结果转换为int
以解决问题。
d <= (int)(TOTAL_ELEMENTS-2)
或者,如果您在许多地方使用宏,那么您可以像这样更改:
#define TOTAL_ELEMENTS (int)(sizeof(array) / sizeof(array[0]))
答案 2 :(得分:5)
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
评估为unsigned
类型。但是,在您的循环中,d
是signed
值。在有符号和无符号值参与的表达式中,有符号值将转换为无符号值。但是d
是-1,它不适合无符号,因此它包裹着&#34;到机器上最高的无符号值(在2&#39;补码)。
答案 3 :(得分:3)
正如其他答案所解释的那样,原因是通常的算术转换,使用sizeof
获得的size_t类型会导致int转换为对应于size_t类型的无符号类型。
我想补充说,行为是实现定义的 1 。可以采用或不采用循环。这取决于size_t类型的定义。
C标准允许类型size_t的排名低于int类型。在这种情况下,整数提升会将类型size_t提升为int类型。此时双方都具有相同的int类型,因此转换将停止。比较d <= (TOTAL_ELEMENTS - 2)
然后产生真,并且循环被采用。
1 因此,程序不严格符合,因为输出依赖于实现定义的行为。
答案 4 :(得分:0)
你知道#define TOTAL_ELEMENTS(sizeof(array)/ sizeof(array [0]))返回一个无符号数,-1可能成为最大数,因为它转换为无符号数。
你可以测试表达式“printf(”%d \ n“,-1&lt; TOTAL_ELEMENTS);”;它打印0.所以我们可以通过在(TOTAL_ELEMENTS - 2)之前添加(int)或改变循环来解决:
const
我不认为让for (int d = 0; d < TOTAL_ELEMENTS; d++) {
printf("%d\n", array[d]); }
变量依赖是一种好方法,因为d
是d
循环中的变量。