6

我们有一个学校项目,任何使用 C 的信息系统。为了保持学生记录的动态大小列表,我选择了链表数据结构。今天早上我的朋友让我看看他的系统。我对他的记录清单感到惊讶:

#include <stdio.h>
/* and the rest of the includes */

/* global unsized array */
int array[];

int main()
{
    int n;
    for (n=0; n < 5; n ++) {
         array[n] = n;
    }


    for (n=0; n < 5; n ++) {
         printf("array[%d] = %d\n", n, array[n]);
    }
    return 0;
}

与代码一样,他声明了一个对整个程序来说是全局(在 bss 段中)的未调整大小的数组。他能够通过用非零值覆盖后续内存块来向数组添加新条目,这样他就可以遍历数组:

for (n=0; array[n]; n++) {
    /* do something */
}

他使用(我也测试过)Turbo C v1。我在 linux 中尝试过,它也可以工作。

由于我以前从未遇到过这种技术,我认为它存在问题。所以,是的,我想知道为什么这是一个坏主意,为什么更喜欢它而不是链表。

4

3 回答 3

7
int array[];

技术上称为类型不完整的数组。简单地说它相当于:

int array[1];

这不好仅仅因为:

  1. 它产生一个未定义的行为。不完整类型数组的主要用途是在Struct Hack中。请注意,在 C99 中标准化的不完整数组类型以前是非法的。
于 2013-03-09T14:56:16.177 回答
4

这是未定义的行为。您正在写入未分配的内存(超出数组)。为了编译它,编译器至少分配了一个元素,然后你在写超出这个元素。尝试更大范围的数字。例如,如果我在 Linux 上运行您的代码,它可以工作,但如果我将循环更改为 50,000,它就会崩溃。

编辑代码可能适用于较小的值,n但对于较大的值,它将失败。为了证明这一点,我编写了您的代码并对其进行了测试n = 1000

这是CODEPAD的链接,您可以看到对于 n = 1000,会发生分段错误

而使用相同编译器的相同代码,它适用于 n = 10,请参阅此链接CODEPAD。所以这被称为未定义的行为

于 2013-03-09T15:00:43.790 回答
0

如果您使用链表,您可以检查内存是否分配正确。

int *ptr;
ptr = (int *)malloc(sizeof(int))
if(ptr==NULL)
{
  printf("No Memory!!!");
}

但是使用您的代码,如果使用具有较大界限的数组进行测试,程序就会崩溃。

于 2013-03-09T15:13:24.733 回答