我们在 File1.c
int arr[10];
在 File2.c 中
extern int *arr;
int main()
{
arr[0]=10;
return 0;
}
这可能会出现什么问题,为什么?
数组不是指针。内存访问将是错误的。
在File1.c
中,您有内存布局:
+---+---+---+---+---+---+---+---+---+---+
+ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+---+---+
^
arr
在File2.c
中,您已经告诉编译器您有内存布局:
+-------+
| ptr |
+-------+
^
arr
其中指针可能指向可以存储整数的地方。
编译器必须做完全不同的事情才能extern int *arr;
从extern int arr[];
.
如所写,最可能的结果是由于编译器取消引用空指针而导致崩溃。但是,行为是未定义的,一切皆有可能。你对编译器撒了谎;编译器会得到自己的回报——它不喜欢被骗。
数组不是指针。
arr
被定义为一个数组,因此也将其声明为一个数组。
extern int arr[10]; // file2.c
如果不这样做,您的程序会调用未定义的行为。
int arr[10];
形式上,本身arr
不占用内存空间;它只是一个可以在链接时确定的地址值。假设arr
是100;arr[0]
是内存地址 100 中的值。
在extern int *arr;
表单中,arr
它本身就是内存中的一个变量。假设 arr 为 100,arr[0]
是内存地址ptr
中ptr
的值,而是地址 100 处的内存单元的值。
编辑
gcc 生成的 asm 给出了深刻的见解:
extern int a[10];
extern int *b;
int foo(void)
{
return a[3] + b[5];
}
_foo:
pushl %ebp
movl %esp, %ebp
movl _b, %eax /* 1st memory load for pointer */
addl $20, %eax
movl (%eax), %eax /* 2nd memory load for pointer */
addl _a+12, %eax /* only one memory load for array */
popl %ebp
ret