2012-07-11 276 views
3

的價值我們在FILE1.C改變外部變量

int arr[10]; 

而在file2.c中

extern int *arr; 

int main() 

{ 
    arr[0]=10; 
    return 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;

書面,最有可能的結果是崩潰,因爲編譯器解引用一個空指針。行爲是未定義的,但是,任何事情都是可能的。你已經對編譯器撒謊了。編譯器會得到它自己的後背—它不喜歡被騙。

3

數組不是指針。

arr被定義爲一個陣列,以便聲明它爲一個數組爲好。

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

如果你不這樣做,你的程序會調用未定義的行爲。

+0

但是爲什麼會發生這種情況,如果我們將它聲明爲指針,那麼未定義的行爲? – Luv 2012-07-11 13:48:46

+0

因爲這兩種類型是不同的,C說如果你不使用正確的類型,你的程序會調用行爲。 – ouah 2012-07-11 13:51:15

0

int arr[10];形式,arr本身不佔用存儲器空間;它只是一個地址值,可以在鏈接時確定。假設arr是100; arr[0]是存儲器地址100中的值。

extern int *arr;窗體中,arr本身是內存中的變量。假設ARR是100,arr[0]是在存儲器地址ptr的值,而ptr是存儲單元的地址處的值100。

EDIT

與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 
+0

使用''......''表示法環繞代碼是非正統的。請使用常規的代碼後置記號表示法。 – 2012-07-11 16:18:48