一个谜题(用C语言编写)

16

一位朋友给了我一个谜语:

#include<stdio.h>

#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]);
      getchar();
      return 0;
  }
上述代码应该会打印出所有数组元素,但是为什么没有输出?我认为循环没有执行一次? 我发现以下代码可以正常工作:
#include<stdio.h>



#define TOTAL_ELEMENTS ((sizeof(array) / sizeof(array[0])))
  int array[] = {23,34,12,17,204,99,16};

  int main()
  {
      int d;
      int x = (TOTAL_ELEMENTS-2);
      for(d=-1;d <= x;d++)
          printf("%d\n",array[d+1]);
      getchar();
      return 0;
  }

我有一个理论,认为这与宏有关,但我无法确定问题所在。


3
当你说某个东西“不起作用”时,你必须说明它实际的表现与你期望的表现有什么不同。 - Gabe
可能是关于C宏展开和整数算术的困惑的重复问题。 - assylias
4个回答

35

问题在于(TOTAL_ELEMENTS-2)是一个无符号值。当你进行比较d <= (TOTAL_ELEMENTS-2)时,两个值都被转换为无符号值,结果是false。

在第二个例子中,x是有符号的,因此没有问题。


5
这就是为什么几乎所有人都会以一种减少有符号/无符号错误的方式编写这种循环:for(d = 0; d < TOTAL_ELEMENTS; d++) printf("%d\n",array[d]); - Zuljin

8
sizeof 运算符返回一个 size_t 类型的结果。在第一种情况下,您正在将一个 int(有符号)与一个 size_t(无符号)进行比较。
在第二种情况下,您通过赋值将 size_t 表达式转换为 int,因此比较的两个操作数类型相同。

3
另一种看待这个问题的方式如下:
#include<stdio.h>

int main() {

int i = -5;
unsigned int j = 6;

if(i < j)
  printf("-5 is less than 6");
else
  printf("-5 is greater than 6");

return 0;
}

输出结果为:

-5 is greater than 6
原因:将无符号整数与有符号整数进行比较将始终返回false。
在提问者的情况下,sizeof返回无符号数据类型,但它与有符号数据类型进行比较(-是一个错误)。

“将无符号整数与有符号整数进行比较将始终返回false。”这是错误的解释。12> 7U计算出预期结果1。interjay的答案已经充分涵盖了这个问题,因此没有必要添加这样一个模糊而不连贯的解释。 - Pascal Cuoq
毫无疑问,我完全同意interjay的答案充分解决了提问者的问题。在我的上一条回复中,我只是试图展示另一个非常简单的代码中相同问题的根本原因。此外,我的解释 - 比较无符号整数和有符号整数将始终返回false,这就是这种特定情况的原因。谢谢。 - SridharKritha

0

我运行了以下程序,没有使用任何宏,但输出为空。

#include<stdio.h>
int main()
{
  int d;
for(d=-1;d<=sizeof(int);d++)
{  
 printf("sizeof operator\n");
}
return 0;
}

这意味着问题不在于,而是sizeof返回的值类型。sizeof返回数据类型的大小,其类型为size_t,即无符号类型,但-1会隐式转换为无符号类型,即0xffffffff,显然大于sizeof(int)。 同时请参考不合规代码示例(比较)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接