【问题标题】:C global unsized array?C全局无大小数组?
【发布时间】:2013-02-25 01:29:16
【问题描述】:

我们有一个学校项目,任何使用 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 中尝试过,它也可以工作。

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

【问题讨论】:

  • 这与写入任何越界数组相同 - 未定义。
  • 这应该是 c99 吗?
  • 1der 请检查 teppic 的更新答案。并打开键盘链接,您可以在代码中观察 C 的未定义行为。

标签: c arrays linked-list


【解决方案1】:
int array[];

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

int array[1];

这不好仅仅因为:

  1. 它会产生一个未定义的行为。不完整类型数组的主要用途是在 Struct Hack 中。请注意,在 C99 中标准化的不完整数组类型在以前是非法的。

【讨论】:

  • 不只是 UB,因为 GCC 说 source.c:4:5: warning: array 'array' assumed to have one element [enabled by default] 这意味着他会在数组的边界之外写出任何超过 1 个元素的内容?
  • 它不是 VLA,它只是写入内存中的随机地址。
  • 嗨,真的是int array[];==int array[1];给我阅读链接..
【解决方案2】:

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

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

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

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

【讨论】:

  • 我在您的答案中添加了更多细节,以演示代码的未定义行为。希望你喜欢。如果没有,您可以恢复到您的版本
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-21
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 2015-07-15
    • 2011-05-18
    相关资源
    最近更新 更多