的價值我們在FILE1.C改變外部變量
int arr[10];
而在file2.c中
extern int *arr;
int main()
{
arr[0]=10;
return 0;
}
什麼是可以用這個,爲什麼會出現問題?
的價值我們在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。
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
使用''......''表示法環繞代碼是非正統的。請使用常規的代碼後置記號表示法。 – 2012-07-11 16:18:48
但是爲什麼會發生這種情況,如果我們將它聲明爲指針,那麼未定義的行爲? – Luv 2012-07-11 13:48:46
因爲這兩種類型是不同的,C說如果你不使用正確的類型,你的程序會調用行爲。 – ouah 2012-07-11 13:51:15