int a[10] = {1, 2, 3, 4, 5, 6, 7, 9, 10};
int *b = a;
extern int a[];
extern int b[];
a[2] = 1; //works well
b[2] = 1; //works well
extern int *a;
extern int b[];
a[2] = 1; // segfault
b[2] = 1; // works well
extern int b[]
匹配int *b
,而extern int a[]
匹配int a[10]
,为什么int []都匹配int *b
(指针)和int a[10]
(一个阵列)同时?
PS:int b []将在codeblocks中抛出编译错误,并在gcc中抛出警告。
答案 0 :(得分:2)
首先:期望C具有类型安全是危险的做法。使用全局变量是一种糟糕而危险的做法。你的计划正在结合这两种危险的做法。
写作时
extern int a[];
extern int b[];
你告诉编译器这两个变量是在别处分配的,并且它不应该关注它在哪里和如何。
然后在另一个文件中声明这些变量,但不是根据您给编译器的规范。相反,您将一个变量更改为指针而不是数组。但由于C具有不存在的类型安全性,因此仍将编译。因此,您有责任确保a和b具有正确的类型。
a[2]=1
当然可以正常工作,因为a
在外部被定义为已分配的数组。
b[2]=1
根本不起作用,你将调用未定义的行为。
因为编译器会将存储b
的内存块视为数组。但实际存储的是一个包含a
地址的指针。在索引[0]这可能有效,你只需要销毁指针变量。但是在索引[1]处,您将在无效的内存位置写入。
解决方案是永远不要使用全局变量和extern
(除非变量是const
)。
答案 1 :(得分:0)
之间的区别
int a[]
int *b;
是'a'是访问数组的编译器名称,其中'b'是一个int指针。 'b'可以重新分配以指向任何int。一个影响是'a'不能重新分配,但'b'可以。
例如,
b = a; //Is Legal
int c[] = {1};
a = c; //Is NOT Legal
此外,在以后使用的大多数上下文中,提及变量'a'将转换为指向数组中第一项的指针。
接下来,'extern'关键字只是告诉编译器不要为给定变量分配内存,因为它是在别处定义的。因此,文件b.c中的extern'a'和'b'只是使文件a.c中的变量'a'和'b'可用于文件b.c。