变量int b []的含义是什么

时间:2014-05-13 13:35:35

标签: c

file a.c

int a[10] = {1, 2, 3, 4, 5, 6, 7, 9, 10};
int *b = a;

file b.c version one

extern int a[];
extern int b[];
a[2] = 1; //works well
b[2] = 1; //works well

file b.c version two

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中抛出警告。

2 个答案:

答案 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。