何時數組與指針相同
全部做爲函數參數的數組名老是能夠經過編譯器轉換爲指針。
在其餘全部狀況下,數組的聲明就是數組,指針的聲明就是指針,二者不能混淆。
但在語句或表達式中引用時,數組老是能夠寫成指針的形式,二者能夠互換。
然而,數組和指針在編譯器處理時是不一樣的,在運行時的表示形式也是不同的。
對編譯器而言,一個數組就是一個地址,一個指針就是一個地址的地址,你應該根據狀況作出選擇。
爲何會發生混淆
當人們學習編程時,一開始老是把全部的代碼都放到一個函數裏。
隨着水平的進步,他們把代碼分別放在幾個函數中。
在水平繼續提升後,他們最終學會了如何用幾個文件來構造一個程序。
何時數組和指針是相同的?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》