在 C 中声明可变长度的数组

Declaring Array in C with variable length

这段代码给出了斐波那契数

#include <stdio.h>

int main()
{
    int n; //integer overflow error for n > 47

    printf("How many Fibonacci numbers?\n");
    scanf("%d", &n);

    int fibs[n];

    fibs[0] = 0;
    fibs[1] = 1;

    printf("%d ", fibs[0]);
    printf("%d ", fibs[1]);

    for(int i = 2; i < n; i++)
    {
        fibs[i] = fibs[i - 2] + fibs[i - 1];
        printf("%d ", fibs[i]);
    }
    return 0;
    //gives 0 1 1 2 3 5 8 13 21 34 for n = 10

}

但这给了我错误的输出但没有错误

#include <stdio.h>

int main()
{
    int n, fibs[n];//change

    printf("How many Fibonacci numbers?\n");
    scanf("%d", &n);

    fibs[0] = 0;
    fibs[1] = 1;

    printf("%d ", fibs[0]);
    printf("%d ", fibs[1]);

    for(int i = 2; i < n; i++)
    {
        fibs[i] = fibs[i - 2] + fibs[i - 1];
        printf("%d ", fibs[i]);
    }
    return 0;
    //gives 0 1 for n = 10
}

我知道这肯定与数组有关,而且它的大小未定义,但我无法理解到底是什么问题。

有人能解释一下这是怎么回事吗?

int n, fibs[n];试图定义一个长度为n的数组,但是n还没有初始化,所以它的值是不确定的。常见后果包括:

  • 定义的行为就好像 n 有一些小值,可能为零,然后下面的代码试图将值存储在数组中,但超出了为它保留的内存,从而破坏了数组所需的其他数据程序。
  • 定义的行为就好像 n 有一些大的值,导致堆栈溢出并终止程序。

例如,将 0 存储到 fibs[0] 或将 1 存储到 fibs[1] 可能会写入为 n 保留的内存。然后 for 循环终止而不执行任何迭代,因为测试 i < n 为假。

我在您的代码中看到的一件大事是行 int n, fibs[n];。变量 n 位于堆栈中,因为它是一个局部变量。这意味着它的值在初始化之前可以是任何值。由于您正在使用该值声明一个数组,因此该数组具有随机的未知长度。如果有效,那纯属巧合。这就是为什么您的第一个代码版本有效的原因,因为数组被声明为 AFTER 初始化 n 的 scanf。我认为创建具有可变数量数组元素的数组的更好方法是改用 malloc...

int n, *fibs;
printf("How many Fibinocci numbers?\n");
scanf("%d", &n);
fibs = malloc(sizeof(int) * n);
if (fibs == NULL)
{
    fprintf(stderr, "Unable to allocate sufficient memory for operation.\n");
    exit(1);
}

然后您可以使用数组索引 fibs[0]、fibs[1] 等...访问内存块中的不同位置。

为什么这行得通?因为 int fibs[n]LIKE 指向一块内存的指针。从技术上讲,它们并不相同,但您通常可以将指向一块内存的指针用作数组。这仅适用于一维数组,因为编译器不知道有多少列。但是要解决这个问题,您可以像这样手动计算(i 是行,j 是列):

数组[i * 列 + j];