7

我最近尝试了这个实验,我没有为未知大小的内存需求进行动态内存分配,而是进行了静态分配。当我声明一个数组a[i]时,我保留i了(数组的大小)变量并依赖于用户提供的输入。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <conio.h>
 void function(int );
 int main(void)
 {
     int i;
     printf("Enter:");
     scanf("%d",&i);
     function(i);
     printf("i = %d\n",i);
     getch();
     return 0;
 }
 void function(int i)
 {
      char a[i];
      char b[4];
      strncpy(a,"hello",i);
      strcpy(b,"world");
      int j = 0;
      char *c = a;
      for( j = 0; j< 20; j++ )
           printf("%c",*c++);
 }

我的问题是:

  • 这样的操作合法吗?
  • 如果不是,为什么编译器不发出任何警告或错误?
  • 该内存将分配到哪里:堆栈还是堆?
  • 为什么 ANSI C/GCC 允许这样做?
4

6 回答 6

16

这样的操作合法吗?

它被称为可变长度数组。

VLA 在 ANSI C99 中是合法的,并且作为一些 C99 之前的编译器的扩展。GCC 支持它作为严格的 C99 和对非 C99 代码的扩展。它在 C++0x 中也是合法的。

如果不是,为什么编译器不发出任何警告或错误?

使用 gcc:

$ gcc -std=c89 src/vla.c  -Wall -ansi -pedantic
src/vla.c: In function ‘function’:, not dynamic array.
src/vla.c:17: warning: ISO C90 forbids variable length array ‘a’
src/vla.c:21: warning: ISO C90 forbids mixed declarations and code

来自 MSDOS 的“conio.h”的存在表明您可能正在使用 Microsoft Visual C++ 编译器,所以不要担心。MS 努力使他们的编译器更符合 C++0x 标准,但没有声明其 C 编译器模式的标准程度。你问为什么法语词典里没有西班牙语方言词。

该内存将分配到哪里:堆栈还是堆?

它是一个自动对象,因此出于效率原因,大多数 C 实现都会放入堆栈。

为什么 ANSI C/GCC 允许这样做

它对于在运行时创建可变大小的临时数组很有用,其生命周期不会超出函数调用。

于 2009-10-31T11:36:02.843 回答
10

这是有效的C99

在此处查看另一个 StackOverflow 问题中的更详细说明。

于 2009-10-31T08:56:26.407 回答
1

这是合法的,但并非所有编译器都支持它。至少 Visual Studio <= 2003 afaik 不支持它。

我假设它不是 Ansi C++,试试 gcc -ansi -pedantic。

于 2009-10-31T08:55:05.083 回答
0

可变长度数组在 ANSI C (C89) 中是非法的。尝试提高编译器的警告级别,我相信您会收到警告/错误。

于 2009-10-31T09:43:20.870 回答
0

堆栈上的动态内存分配:

有一个库调用 _malloca 在程序堆栈上动态分配内存(非常像 malloc 在堆上所做的那样)

参考:_malloca

于 2010-07-13T06:50:11.527 回答
0

代码是有效的,但是在使用可变长度数组时要记住一件事。

void function(int i)
{
     int a[i];
     .
     .
}

这里没有错误检查。i如果太大,此代码可能会失败。

于 2009-10-31T18:43:52.960 回答