我想在main.c中使用来自foo.c的变量a,我写道:
foo.c
#include <stdio.h>
int a[] = {3, 2};
void foo()
{
printf("foo\taddress of a:%x\n", a);
printf("foo\tvalue of a[0]:%x\n", a[0]);
}
main.c
#include <stdio.h>
extern int *a;
int main(void)
{
foo();
printf("main\taddress of a : %x\n", a);
printf("main\tvalue of a[0] : %x\n", a[0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和结果输出:
foo address of a:804a014
foo value of a[0]:3
main address of a : 3
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)
为什么?
类型a是int[2],而不是int*.再试一次
extern int a[2];
Run Code Online (Sandbox Code Playgroud)
C编译器无法跨源文件进行类型检查.因此,当你说int* a,编译器将假设你说实话,使用指针语义,并且不会发出任何编译器错误.
数组和指针之间存在细微差别.我们假设一个32位系统.然后"a"的内容将像这样分发:
a
0x100 0x104 0x108 ? address
+-----------+----------+
| 3 | 2 | ? content
+-----------+----------+
什么时候a是数组,
a将转换为地址a.因此,当您打印时a,您将获得其地址,即"0x100".a[n]C中的操作相当于*(a + n),即a按n单位推进地址,然后取消引用它以获取内容.因此,a[0]相当于*0x100将内容返回0x100,即"3".当a是一个指针,
a是提供的地址的内容.实际上这是常态,数组类型是一种特殊情况.因此,当您打印时a,您将获得该地址的内容,即"3".a[n]还在*(a + n).因此,a[0]等同于*3导致分段错误,因为地址"3"无效.