2013-02-26 275 views
2

我有一個非常普遍的問題,當我試圖寫一個字符數組到一個文件中,我寫的代碼C編譯器警告

fwrite(array[10],1,10,file_ptr) 

和編譯器扔了警告argument 1 makes from integer to pointer without a cast.

然後我將該行修改爲

fwrite(&array[10],1,10,file_ptr) 

並且警告現在不再顯示。

問題:編譯器如何區分地址和值?如果array[10]的值類似於正確的地址,該怎麼辦?

+0

你能告訴我們'array'的聲明嗎? – Jens 2013-02-26 09:07:03

回答

1

C是靜態類型語言。當你寫

char array[100]; 

你說的是C編譯器是array是100個字符數組。然後,它知道array[10]是一個字符,而&array[10]是一個指向字符的指針(一個char *)。

fwrite雖然被定義爲將const void *作爲其第一個參數,即無類型指針。如果你通過它不是一個指針,編譯器知道這一點,並會抱怨。

您的C編譯器不會嘗試「猜測」某種東西的類型是基於它的值。

4

如果有十個字符的陣列,即

char array[10]; 

然後做array[10]訪問該陣列的第十一元件。

簡單地傳遞數組變量,它可以作爲一個指針:

fwrite(array, 1, 10, file); 
+0

+1,因爲您指出了錯誤,但「作爲指針工作」更像是「衰減成指針」。 – 2013-02-26 08:20:29

1

fwrite()簽名是:fwrite(const void *ptr, size_t size, size_t count, FILE *fptr)

fwrite()期待一個地址(或保持該地址,又名指針的指針變量),而不是一個字符,但, a[10]是一個字符,而不是指針。這是警告的原因!

&a[10]的地址,作爲fwrite()的第一個參數的有效適合。因此沒有警告!


它如何保存信息是在其詞法分析器組合和語義分析器在一個名爲「符號表」的表中。

- 在問題編輯後 -

fwrite(&array[10],1,10,file_ptr) < - 參數-1被解釋爲從11位置開始的字符串中array

+3

地址不一定是4個字節寬,它與問題無關。而且你也不需要提及詞法分析器和解析器。 – 2013-02-26 08:34:11

+0

@AlexeyFrunze我之所以提到這一切是因爲'編譯器如何區分地址和值?如果數組[10]的值與正確的地址相似,該怎麼辦? – 2013-02-26 08:37:10

+0

編譯器跟蹤變量類型,這足以讓人知道。 – 2013-02-26 08:39:58

1

看來你的印象是array[10]指定下整個數組 - 它不。它指定array的第11個元素,它不存在(假設您聲明爲some_type array[10])。因爲在C中,名稱是一個數組,因此您需要將fwrite()作爲array的第一個元素的地址,這恰好就是array(或&array[0]),因爲在C中,數組在表達式中使用時,是其第一個元素的地址(除了sizeof運算符)。

編譯器具有關於數組類型和元素類型的完整信息,因此它可以檢測何時在需要指針的位置編寫int類型的表達式。

有一種方法來fwrite()將一個完整的陣列,獨立大小和元件類型的,只使用陣列標識符:

fwrite (array, sizeof *array, sizeof array/sizeof *array, file); 

其中sizeof *array計算結果爲元件的尺寸和sizeof array/sizeof *array評估爲的數量數組中的元素。請注意,這適用於數組,只適用於,不適用於指針。同樣可以用

fwrite (array, sizeof array, 1, file); 

fwrite (array, 1, sizeof array, file); 

它基本上是你喜歡的風格問題來實現;它們都是等效的,並且將以相同的速度執行。

0

如果數組[10]的值類似於正確的地址會怎麼樣?

那麼你的數組類型本來int (*)[n],而不是int [n]。這就是爲什麼我們有一個類型系統。