访问未定义的外部数组
Accessing an Undefined External Array
我正在研究 K&R,所以请原谅我对 C 的平庸理解。我正在尝试将 argv 的值作为整数存储在外部数组中。所以我的第一个问题是:是否可以创建一个大小取决于 argc 的外部数组?或者除了使用任意长的数组并希望它全部适合之外,是否有任何解决方法。
其次,我尝试使用指向未定义整数数组的指针。我能够多次增加指针,在我得到 "Bus error: 10." 之前读取(几乎所有内容都为零)和写入指向的内存是否有原因我能够访问这么多内存在我遇到总线错误之前,或者这只是 "undefined behavior?"
的一部分
这是测试未定义数组的代码。
#include <stdio.h>
int main(void);
int test();
int a[];
int main(void)
{
test();
}
int test()
{
extern int a[];
int *a0 = a;
printf("%d\n", *a0);
while (1) {
*a0 = 1;
a0++;
printf("%d\n", *a0);
}
return 0;
}
is it possible to create an external array with size dependent on argc
?
不是真的。您可以分配一个数组并将指向它的指针存储到全局存储段中,但它是一个指针,而不是数组。
I was able to increment the pointer a large number of times, both reading from (almost everything was zero) and writing to the pointed memory before I got a "Bus error: 10."
数组外的第一个读或写是非法的。您没有立即获得 "Buss Error: 10." 的事实是一个不幸的巧合,因为代码可能在实际不正确的时候看起来有效。
is that all just part of "undefined behavior?"
是的,这是未定义的行为。
首先,让我们澄清一下 extern 的作用。在 C 中,有一种叫做翻译单元的东西。现在,将它们想象成只是 .c 文件。编译它们时,每个 .c 文件形成一个翻译单元并生成一个目标文件 (.o)。然后将目标文件放在一起,由链接器创建最终的可执行文件。有时你想在一个翻译单元中定义(即 "create")一些东西,比如数组,但在多个翻译单元中使用它。就 C 而言,这很好:一切都必须定义一次,但可以多次使用。但是,您需要通知编译器您希望在另一个翻译单元中定义该数组,而不是定义另一个数组。为此,您可以使用 extern 关键字。
在你的例子中,你的数组 a 只是一个全局数组,可以从这个翻译单元的任何地方访问(即在这个文件中)。所以,你真的不需要在主函数中使用 extern 关键字声明它。
你真正想问的是是否可以创建一个大小等于 argc 的全局数组。
直到 C99(K&R 是 C99 之前的版本),数组的大小必须是常量。所以你必须创建一个足够大的数组。但是,您不应该希望它适合 - 这是创建错误和漏洞的一种非常常见的方式。相反,您应该检查其用法是否合理,如果超出大小,则生成错误。如果你不这样做,你会得到未定义的行为。它可能有效,也可能无效。并且它可能被用于恶意目的。
C99 标准支持可变长度数组,因此您可以使用 int a[argc]; 之类的东西。但是,这仅适用于本地数组。
解决方案是创建一个全局指针并在主函数中使用 malloc 函数为其动态分配内存。
我正在研究 K&R,所以请原谅我对 C 的平庸理解。我正在尝试将 argv 的值作为整数存储在外部数组中。所以我的第一个问题是:是否可以创建一个大小取决于 argc 的外部数组?或者除了使用任意长的数组并希望它全部适合之外,是否有任何解决方法。
其次,我尝试使用指向未定义整数数组的指针。我能够多次增加指针,在我得到 "Bus error: 10." 之前读取(几乎所有内容都为零)和写入指向的内存是否有原因我能够访问这么多内存在我遇到总线错误之前,或者这只是 "undefined behavior?"
的一部分这是测试未定义数组的代码。
#include <stdio.h>
int main(void);
int test();
int a[];
int main(void)
{
test();
}
int test()
{
extern int a[];
int *a0 = a;
printf("%d\n", *a0);
while (1) {
*a0 = 1;
a0++;
printf("%d\n", *a0);
}
return 0;
}
is it possible to create an external array with size dependent on
argc
?
不是真的。您可以分配一个数组并将指向它的指针存储到全局存储段中,但它是一个指针,而不是数组。
I was able to increment the pointer a large number of times, both reading from (almost everything was zero) and writing to the pointed memory before I got a "Bus error: 10."
数组外的第一个读或写是非法的。您没有立即获得 "Buss Error: 10." 的事实是一个不幸的巧合,因为代码可能在实际不正确的时候看起来有效。
is that all just part of "undefined behavior?"
是的,这是未定义的行为。
首先,让我们澄清一下 extern 的作用。在 C 中,有一种叫做翻译单元的东西。现在,将它们想象成只是 .c 文件。编译它们时,每个 .c 文件形成一个翻译单元并生成一个目标文件 (.o)。然后将目标文件放在一起,由链接器创建最终的可执行文件。有时你想在一个翻译单元中定义(即 "create")一些东西,比如数组,但在多个翻译单元中使用它。就 C 而言,这很好:一切都必须定义一次,但可以多次使用。但是,您需要通知编译器您希望在另一个翻译单元中定义该数组,而不是定义另一个数组。为此,您可以使用 extern 关键字。
在你的例子中,你的数组 a 只是一个全局数组,可以从这个翻译单元的任何地方访问(即在这个文件中)。所以,你真的不需要在主函数中使用 extern 关键字声明它。
你真正想问的是是否可以创建一个大小等于 argc 的全局数组。
直到 C99(K&R 是 C99 之前的版本),数组的大小必须是常量。所以你必须创建一个足够大的数组。但是,您不应该希望它适合 - 这是创建错误和漏洞的一种非常常见的方式。相反,您应该检查其用法是否合理,如果超出大小,则生成错误。如果你不这样做,你会得到未定义的行为。它可能有效,也可能无效。并且它可能被用于恶意目的。
C99 标准支持可变长度数组,因此您可以使用 int a[argc]; 之类的东西。但是,这仅适用于本地数组。
解决方案是创建一个全局指针并在主函数中使用 malloc 函数为其动态分配内存。