在 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];
这段代码给出了斐波那契数
#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];