简体   繁体   English

C中变长arrays难理解

[英]Difficulty in understanding variable-length arrays in C

I was reading a book when I found that array size must be given at time of declaration or allocated from heap using malloc at runtime.I wrote this program in C:我在看书时发现数组大小必须在声明时给出或在运行时使用 malloc 从堆中分配。我在 C 中编写了这个程序:

#include<stdio.h>

int main() {
  int n, i;
  scanf("%d", &n);
  int a[n];
  for (i=0; i<n; i++) {
    scanf("%d", &a[i]);
  }
  for (i=0; i<n; i++) {
    printf("%d ", a[i]);
  }
  return 0;
}

This code works fine.此代码工作正常。

My question is how this code can work correctly.Isn't it the violation of basic concept of C that array size must be declared before runtime or allocate it using malloc() at runtime.I'm not doing any of these two things,then why it it working properly?我的问题是这段代码如何正确工作。这是否违反了 C 的基本概念,即必须在运行前声明数组大小或在运行时使用 malloc() 分配它。我没有做这两件事中的任何一件,那为什么它能正常工作呢?

Solution to my question is variable length arrays which are supported in C99 but if I play aroundmy code and put the statement int a[n];我的问题的解决方案是可变长度 arrays,它在 C99 中受支持,但是如果我绕过我的代码并将语句放入 int a[n]; above scanf("%d,&n); then it's stops working Why is it so.if variable length arrays are supported in C?以上 scanf("%d,&n); 然后它停止工作 为什么会这样。如果 C 支持可变长度 arrays?

The C99 standard supports variable length arrays . C99 标准支持可变长度 arrays The length of these arrays is determined at runtime.这些 arrays 的长度是在运行时确定的。

Since C99 you can declare variable length arrays at block scope.从 C99 开始,您可以在块 scope 处声明可变长度 arrays。

Example:例子:

void foo(int n)
{
    int array[n];

    // Initialize the array
    for (int i = 0; i < n; i++) {
        array[i] = 42;
    }
}

C will be happy as long as you've declared the array and allocated memory for it before you use it. C 会很高兴,只要您在使用它之前声明了数组并为其分配了 memory。 One of the "features" of C is that it doesn't validate array indices, so it's the responsibility of the programmer to ensure that all memory accesses are valid. C 的“特性”之一是它不验证数组索引,因此程序员有责任确保所有 memory 访问都是有效的。

Variable length arrays are a new feature added to C in C99.变长arrays是C99中C新增的特性。

"variable length" here means that the size of the array is decided at run-time, not compile time.这里的“可变长度”意味着数组的大小是在运行时决定的,而不是编译时决定的。 It does not mean that the size of the array can change after it is created.这并不意味着数组的大小在创建后可以改变。 The array is logically created where it is declared.该数组逻辑上是在声明它的地方创建的。 So your code looks like.所以你的代码看起来像。

int n, i;

Create two variables n and i.创建两个变量 n 和 i。 Initially these variables are uninitialised.最初这些变量是未初始化的。

scanf("%d", &n);

Read a value into n.将一个值读入 n。

int a[n];

Create an array "a" whose size is the current value of n.创建一个数组“a”,其大小为 n 的当前值。

If you swap the second and third steps you try to create an array whose size is determined by an uninitalised value.如果您交换第二步和第三步,您会尝试创建一个数组,其大小由未初始化的值决定。 This is not likely to end well.这不太可能有好结果。

The C standard does not specify exactly how the array is stored but in practice most compilers (I belive there are some exceptions) will allocate it on the stack. C 标准没有具体指定数组的存储方式,但实际上大多数编译器(我相信有一些例外)会将其分配到堆栈上。 The normal way to do this is to copy the stack pointer into a "frame pointer" as part of the function preamble.执行此操作的正常方法是将堆栈指针复制到“帧指针”中,作为 function 序言的一部分。 This then allows the function to dynamically modify the stack pointer while keeping track of it's own stack frame.然后,这允许 function 动态修改堆栈指针,同时跟踪它自己的堆栈帧。

Variable length arrays are a feature that should be used with caution.可变长度 arrays 是一个应该谨慎使用的特性。 Compilers typically do not insert any form of overflow checking on stack allocations.编译器通常不会对堆栈分配插入任何形式的溢出检查。 Operating systems typically insert a "gaurd page" after the stack to detect stack overflows and either raise an error or grow the stack, but a sufficiently large array can easilly skip over the guard page.操作系统通常会在堆栈后插入一个“保护页面”以检测堆栈溢出并引发错误或增加堆栈,但足够大的数组可以轻松跳过保护页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM