我们在File1.c
int arr[10];
在File2.c中
extern int *arr;
int main()
{
arr[0]=10;
return 0;
}
这可能会出现什么问题?为什么?
答案 0 :(得分:11)
数组不是指针。内存访问是错误的。
在File1.c
中,您有内存布局:
+---+---+---+---+---+---+---+---+---+---+
+ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+---+---+
^
arr
在File2.c
中,您告诉编译器您有内存布局:
+-------+
| ptr |
+-------+
^
arr
其中指针可能指向可以存储整数的地方。
编译器必须完全不同地从extern int *arr;
访问extern int arr[];
。
如上所述,最可能的结果是崩溃,因为编译器取消引用空指针。但是,行为是未定义的,任何事情都是可能的。你骗了编译器;编译器会自己回来 - 它不喜欢被骗。
答案 1 :(得分:3)
数组不是指针。
arr
被定义为数组,因此也将其声明为数组。
extern int arr[10]; // file2.c
如果不这样做,程序将调用未定义的行为。
答案 2 :(得分:0)
在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