在下面的代码中,
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int main(void){
int array[] = {7,5,4,3,2};
int index = -1;
for(;index <= TOTAL_ELEMENTS-2;index++)
printf("%d\n", array[index+1]);
return 0;
}
index <= TOTAL_ELEMENTS-2
在打印单个元素之前失败。
不是条件-1 <= (5-2)
,正在for-loop
进行评估吗?
答案 0 :(得分:2)
sizeof(array) / sizeof(array[0])
会产生5
,类型为size_t
。因此,表达式sizeof(array) / sizeof(array[0])-2
的类型也是size_t
,它是无符号整数类型。比较的LHS也会升级为size_t
类型(请参阅usual arithmeic conversions),-1
等于转换后的SIZE_MAX(size_t
可以容纳的最大值)
因此,相当于index <= TOTAL_ELEMENTS-2
的比较SIZE_MAX <= 3
是错误的。
答案 1 :(得分:1)
除法sizeof(array)/sizeof(array[0])
导致unsigned int,因此当与index = -1比较或从中减去它时,将隐式转换为unsigned int,即0xffffffff,因此条件失败。
相反,只需在宏中进行显式转换
#define TOTAL_ELEMENTS (int)(sizeof(array) / sizeof(array[0]))
我个人会改为使用你的TOTAL_ELEMENTS的参数
#define TOTAL_ELEMENTS(ar) (int)(sizeof(ar))/sizeof(ar[0]))
使代码更具可读性。
答案 2 :(得分:0)
在比较index <= TOTAL_ELEMENTS-2
中,左侧index
的类型为int
,右侧TOTAL_ELEMENTS-2
的类型为size_t
¹。运算符的两个操作数具有不同的类型,因此需要将它们转换为通用类型。常见类型总是具有两个大小²中的较大者,即size_t
(在32位计算机上可能与unsigned int
相同,但在64位计算机上通常更大)。在这种情况下,普通类型是无符号的,因为右侧至少是那么大。
始终选择公共类型,以便它可以表示两种类型的最大正值。如果这导致无符号类型,则它不能表示负值。
此处变量index
是一个数组索引,因此它应该具有类型size_t
。类型int
可能太小而无法表示所有数组索引。
size_t
是无符号类型;无符号值更易于操作,并且在溢出时具有可预测的行为,因此一般来说,除非需要负值,否则应使用无符号类型。 (溢出仍然是无符号类型的问题,但至少行为是明确定义的,因此问题更容易调试。)这里有一个带负值的变量没有意义:使用index
作为数组索引,而不是数组索引减1,然后它将从0开始而不是1。
size_t index;
for(index = 0; index <= TOTAL_ELEMENTS-1; index++) {
printf("%d\n", array[index]);
}
如果unsigned int
小于size_t
,则¹或int
,例如如果它是unsigned short
,但对于C实现来说这是非常不寻常的。 子>
²在技术方面,两个等级中较大者。