C語言專題——數組與指針

C語言專題——數組與指針

什麼時候數組與指針相同

所有作爲函數參數的數組名總是可以通過編譯器轉換爲指針。
在其他所有情況下,數組的聲明就是數組,指針的聲明就是指針,兩者不能混淆。

但在語句或表達式中引用時,數組總是可以寫成指針的形式,兩者可以互換。

然而,數組和指針在編譯器處理時是不同的,在運行時的表示形式也是不一樣的。
對編譯器而言,一個數組就是一個地址,一個指針就是一個地址的地址,你應該根據情況做出選擇。
 
爲什麼會發生混淆

當人們學習編程時,一開始總是把所有的代碼都放到一個函數裏。
隨着水平的進步,他們把代碼分別放在幾個函數中。
在水平繼續提高後,他們最終學會了如何用幾個文件來構造一個程序。

什麼時候數組和指針是相同的?C語言標準對此作了如下說明:
規則1 表達式中的數組名(與聲明不同)被編譯器當作一個指向該數組第一個元素的指針。
規則2 下標總是與指針的偏移量相同。
規則3 在函數參數的聲明中,數組名被編譯器當作指向該數組的第一個元素的指針。
 
規則1:“表達式中的數組名”就是指針

規則1和2合在一起理解,就是對數組下標的引用總是可以寫成“一個指向數組的起始地址的指針加上偏移量。”
(個人認爲,表述爲“一個指向該數組第一個元素的指針加上偏移量”更明確。)

對數組的引用如a[i]在編譯時總是被編譯器改寫成*(a+i)的形式。
C語言標準要求編譯器必須具備這個概念性的行爲。
於是,a[6]和6[a]都是正確的。

編譯器自動把下標值的步長調整到數組元素的大小。
這就是爲什麼指針總是有類型限制,每個指針只能指向一種類型的原因,
因爲編譯器需要知道對指針進行解除引用操作時應取幾個字節,以及每個下標的步長應取幾個字節。
 
規則2:C語言把數組下標作爲指針的偏移量

事實上,下標範圍檢測被認爲並不值得加入到C語言中。

數組下標是定義在指針的基礎上的,所以優化器常常可以把它轉換爲更有效率的指針表達式,
並生成相同的機器指令。

C語言把數組下標改寫成指針偏移量的根本原因是指針和偏移量是底層硬件所使用的基本模型。
 
爲什麼C語言把數組形參當作指針

之所以要把傳遞給函數的數組參數轉換爲指針是出於效率的考慮,
這個理由常常也是對違反軟件工程做法的辯解。

我們傾向於始終把參數定義爲指針,因爲這是編譯器內部所使用的形式。
但從另一方面,有些人覺得int table[]比int *table更能表達程序員的意圖。
 
數組片段的下標

向函數傳遞數組前面一個位置的地址(a[-1]),這樣就可以使數組下標從1到N,而不是從0到N-1。
不幸的是,這個手段完全爲標準所不容,所以你千萬不要告訴別人是我告訴了你這個方法。
 
C語言的多維數組
 
但所有其他語言都把這稱爲“數組的數組”

C語言裏有一種別的語言稱爲數組的數組的形式,但C語言稱它爲多維數組。
C語言中的數組就是一維數組,而這個數組的元素可以是另一個數組。

編譯器在編譯時會把carrot[i][j]解析爲*(*(carrot+i)+j)的形式。
 
如何分解多維數組

在“數組的數組的數組”中的每一個單獨的數組都可以看作是一個指針。
這是因爲在表達式中的數組名被編譯器當作“指向數組第一個元素的指針”。
 
內存中數組是如何佈局的

在C語言的多維數組中,最右邊的下標是最先變化的,這個約定稱爲“行主序”。
 
如何對數組進行初始化

只能夠在數組聲明時對它進行整體的初始化。
之所以存在這個限制,並沒有過硬的理由。

在IEEE754標準浮點數實現中,0.0和0的位模式是完全一樣的。

初始化二維字符串數組:
char vegetables[][9] =
{
 "beet",
 "barley",
 "basil",
 "broccoli",
 "beanes"
};

一種有用的方法是建立指針數組,字符串常量可以數組初始化值:
char *vegetables[] =
{
 "beet",
 "barley",
 "basil",
 "broccoli",
 "beanes"
};
 
source: 《Expert C Programming》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章