【问题标题】:variable-length array and segmentation fault可变长度数组和分段错误
【发布时间】:2012-05-04 21:21:15
【问题描述】:

在下面的代码中,如果我在扫描所需长度的数组“x”之前声明了可变长度数组“int array1[x]”,我会在执行时收到“分段错误(核心转储)”。 (编译没有错误)。我在编译时使用选项 -std=c99 严格使用了 ANSI C99 标准。

我的问题是为什么我不能将所有声明组合在一起?

// code to find a minimum value in a variable-length array
#include<stdio.h>

int minval(int [], int); 

int main(void)
{
    int x, i;

    int minivalue;

    printf("Enter the total number of array elements you wish to define?");
    scanf("%i",&x);

    int array1[x];          

    printf("Enter the elements now:");
    for (i = 0; i < x; i++)
        scanf("%i",&array1[i]);

    minivalue = minval(array1, x);

    printf("\nMinimum value in the array is = %i\n",minivalue);

    return 0;
}

int minval(int array2[], int x)     
{
    int i;
    int minivalue;

    minivalue = array2[0];

    for (i=0; i < x; i++){
        if (minivalue > array2[i])
            minivalue = array2[i];  
    }

    return (minivalue);
}

【问题讨论】:

  • 那不是有效的 C。我真的很惊讶它甚至可以编译。您需要使用动态内存分配(即malloc)。
  • 它编译并正常运行。我也使用 -std=c99 选项进行编译。
  • 那么它要么是 GCC 扩展,要么是标准中的特殊情况(我怀疑是 GCC 扩展)。
  • @Corbin 但为什么它无效。标准规定变量可以在程序的任何地方声明,只要声明发生在变量第一次使用之前。
  • 因为你不能用这样的变量声明一个数组。 int a[x] 被视为无效。那是因为它依赖于动态分配。这是因为 x 的值在编译时是未知的。如果 x 的值在编译时已知,则它是有效的。我怀疑当你把它放在之后发生的事情是 GCC 扩展会自动将它转换为 Emanuele Bezzi 的答案。之前放置它时,GCC 会做同样的事情,除了 x1 没有初始化,因此 malloc 有可能出错。

标签: c arrays variable-length


【解决方案1】:

在下面的代码中,如果我在扫描数组“x”的所需长度之前声明了可变长度数组“int array1[x]”,我会在执行时收到“分段错误(核心转储)”。

您不能声明具有未初始化值的可变长度数组。

当您将int array1[x] 移动到scanf() 之前时,x 没有有效值。

【讨论】:

  • 但是 x 实际上是在程序运行时初始化的。那么在编译时是否初始化 x 对编译器有什么影响呢?如果除了数组声明的位置没有改变,我无法理解为什么编译器的行为会有所不同?
  • 不,x 未初始化。要进行初始化,您必须拥有int x = 42;。使用普通的int x;,您只是定义 x
  • 现在我的问题是,如果在扫描语句之前或之后声明一个数组,对编译器有什么影响?记住变量,这个数组使用已经声明了!..
  • 声明不是定义。声明 (int x;) 告诉编译器正在声明的名称是某种类型的对象;定义 (int x = 42;) 告诉编译器与声明 对象值相同。在您的问题代码中,声明了名为 x 的对象,未初始化......它的值是垃圾,直到它被分配一个值(在 scanf() 调用中)。
【解决方案2】:

替换

int array1[x]; 

int* array1 = (int*) malloc (x * sizeof int);

所以你分配了足够的内存来让array1中包含x个元素。

之后不要忘记释放内存,通过添加

free(array1)

在程序结束时。

【讨论】:

  • -1。这并不能解决他的问题。可变长度数组是有效的 C99。当他将语句向上移动时,当前发生的情况是 x 未初始化。段错误可能是由于值太大和堆栈溢出引起的。如果他移动了声明但按照您的建议使用了malloc,它只是隐藏了问题。如果x 持有值&gt;=,分配可能会成功,但您仍然依赖于未定义的行为。
  • X 仅在运行时初始化。不是吗?那么将数组声明移到扫描语句下方是如何帮助代码运行的呢?那是我的问题..
【解决方案3】:

@Saurabh:尝试使用 C99 标准在运行时播放“计算机”。你遇到了声明 int x。它有一些很大的垃圾价值。然后您读取具有较大值的数组声明-您尝试分配该值-堆栈内存不足-您出现段错误。相反,如果您先读取大小合理的 x 值,然后再读取数组分配,您就可以在堆栈上分配内存。无论如何,这个 c99 功能很糟糕。改用 std::vector。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-04
    • 2020-09-01
    • 2021-08-09
    • 2020-11-20
    • 2013-05-16
    • 2014-09-18
    • 1970-01-01
    相关资源
    最近更新 更多