更改外部变量的值

时间:2012-07-11 13:40:53

标签: c extern

我们在File1.c

int arr[10];

在File2.c中

extern int *arr;

int main()

{
   arr[0]=10;
   return 0;
}

这可能会出现什么问题?为什么?

3 个答案:

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