Changing the value of an external variable

2019-03-31 07:52发布

问题:

We have in File1.c

int arr[10];

And in File2.c

extern int *arr;

int main()

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

What are the problems that can occur with this and why?

回答1:

An array isn't a pointer. The memory access will be wrong.

In File1.c, you have the memory layout:

+---+---+---+---+---+---+---+---+---+---+
+ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+---+---+
^
arr

In File2.c, you've told the compiler you have the memory layout:

+-------+
|  ptr  |
+-------+
^
arr

where the pointer presumably points somewhere that an integer can be stored.

The compiler has to do things totally differently to access extern int *arr; from extern int arr[];.

As written, the most likely result is a crash as the compiler dereferences a null pointer. The behaviour is undefined, though, and anything is possible. You've lied to the compiler; the compiler will get its own back — it does not like being lied to.



回答2:

Arrays are not pointers.

arr is defined to be an array so declare it as an array as well.

extern int arr[10];   // file2.c

If you don't, your program invokes undefined behavior.



回答3:

In the int arr[10]; form, arr itself does not occupy memory space; it is just an address value that can be determined at link time. Suppose arr is 100; arr[0] is the value in memory address 100.

In the extern int *arr; form, arr itself is a variable in memory. Suppose arr is 100, arr[0] is the value in memory address ptr, while ptr is the value of memory cell at address 100.

EDIT

The asm generated by gcc gives a deep insight:

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


标签: c extern