使用比较运算符

时间:2016-10-30 12:20:40

标签: c

在下面的代码中,

#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进行评估吗?

3 个答案:

答案 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实现来说这是非常不寻常的。
²在技术方面,两个等级中较大者。