【问题标题】:Printing array elements打印数组元素
【发布时间】:2011-03-23 22:11:45
【问题描述】:

以下 C 程序的预期输出是打印数组元素。但是当实际运行时,它并没有这样做。

#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]);

    return 0;
}

是什么原因?

【问题讨论】:

  • 为什么不简单地for (d = 0; d &lt; TOTAL_ELEMENTS; ++d)
  • 也许这是一个有启发性的例子,说明用 C 正确编程是多么困难。鉴于此,它确实是一个很好的例子。
  • 这个问题是Gowri Korumar's C puzzles 的一部分,它是 50 个非常有教育意义的 C 问题的汇编。我从过去的知识和研究中回答了前 25 个问题,以防万一:C puzzles answered

标签: c arrays


【解决方案1】:

TOTAL_ELEMENTS 未签名。 -1,当转换为无符号时,是一个非常大的数字,不少于 6。因此,您的循环永远不会运行。

【讨论】:

  • 是的......你不应该在没有正当理由的情况下混合有符号/无符号的分配或比较,在这种情况下,明确的转换已经到位。此外,如果设置了适当的警告级别,大多数编译器都应该为此发出警告。
【解决方案2】:

当您进行比较d &lt;= (TOTAL_ELEMENTS-2) 时,会执行类型转换dsigned int 类型,而 (TOTAL_ELEMENTS-2)size_t 类型,这是一个无符号类型。 C 的规则说,当一个运算符有一个有符号和一个无符号参数,并且无符号参数的大小大于或等于有符号参数时,则将有符号参数转换为无符号参数。

也就是说,比较结果为:

(size_t) d <= (TOTAL_ELEMENTS-2)

因为size_t 是无符号的,(size_t) -1 是一个非常非常大的数字,不再是-1。对于 32 位 size_t,它将是 232 - 1 = 4,294,967,295。

要解决此问题,您可以将右侧显式转换为带符号的 int:

d <= (int) (TOTAL_ELEMENTS-2)

或者,更好的是,摆脱奇怪的负索引等。

为了将来参考,请尽可能打开所有编译器警告。例如,如果你打开-Wall -Wextra,gcc 会打印一个警告:

$ gcc -o arrayprint -Wall -Wextra -ansi arrayprint.c 
arrayprint.c: In function ‘main’:
arrayprint.c:11: warning: comparison between signed and unsigned

【讨论】:

  • 除了将宏的结果转换为int之外,从一开始就使用size_t作为d并使用适当的边界0作为开始和d &lt; TOTAL_ELEMENTS 条件。
【解决方案3】:

起初,我不知道。但是当我使用 GCC 编译它时,很明显:

$ gcc -Wall -Wextra -Os a.c
a.c: In function `main':
a.c:11: warning: comparison between signed and unsigned

所以你有一个比较如下:

(int) -1 <= (size_t) 5

由于其中一种类型是有符号的,另一种是无符号的,因此首先需要将它们转换为通用类型。在这种情况下,它是size_t。就是这样:

(size_t) -1 <= (size_t) 5

现在-1 不能用无符号类型表示。因此,将 2^32(或 size_t 有多少位)添加到它,使其成为 4294967295。所以比较真的是:

4294967295 <= 5

那是false,因此永远不会执行循环体。

【讨论】:

    【解决方案4】:

    原因是循环永远不会执行。这是因为TOTAL_ELEMENTS 返回一个size_t,一个无符号类型。

    您可以通过将 (TOTAL_ELEMENTS-2) 转换为 int 来解决此问题。

    【讨论】:

      【解决方案5】:

      您需要执行以下操作:

      for(d=0;d < TOTAL_ELEMENTS;d++)
          printf("%d\n",array[d]);
      

      sizeof(...) 产生一个无符号值。

      【讨论】:

        【解决方案6】:

        简单的改变

        #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
        

        #define TOTAL_ELEMENTS (int)(sizeof(array)/sizeof(array[0]))-2
        

        【讨论】:

        • 你真的把它弄错了。数组索引应该总是size_t。他只需将d 更改为size_t 并进行适当的索引,所有的模糊都会消失......
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-22
        • 1970-01-01
        • 1970-01-01
        • 2013-05-06
        相关资源
        最近更新 更多