數組
一 關於數組的初始化
例:int p[4]={1,2,3,4};
1 未經初始化的數組
auto類型的(自動儲存類)的數組在初始化之前數組元素是不定的,編譯器使用的在儲存單元中已有的數值。
靜態儲存式時期的數組自動將所有元素初始化為零
2 部分初始化
int p[4]={1,2};
則 p[0]=1,p[1]=2,p[3]=p[4]=0;
也就是說如果只初始化了數組中的部分元素,則剩餘的元素自動初始化為0,因此如果要將一個數組全部初始化為零可以這樣做p[MAX]={0}
3 指定項目初始化 ( C99 )
按照傳統的方法要對數組的最後一個元素初始化,需要對每個元素都初始化之後才可以對最後一個元素進行初始化。
例如: int a[5]={0,0,0,0,16};
在 C99標準中可以用其新特性,指定初始化項目來簡單的完成上述工作
例如:int a[5]={[5]=16};
在初始化列表中使用帶方括弧的元素下標可以指定某個特定元素
例: d[8]={1,2,[4]=9,10,11,[1]=15};
則 d[0]=1,d[1]=15,d[2]=0,d[3]=0,d[4]=9,d[5]=10,d[6]=11
註:指定項目初始化的兩個重要特性
若在一個指定初始化項目後跟有不止一個值,則這些值將用來對後續的數組元素初始化。因此在d[4]=9之後,d[5].d[6]分別初始化為10,11
如果多次對一個元素初始化,則最後一次有效.例中d[1]先被初始化為2,在[1]=15之後,d[1]又初始化為15。
指標和數組
c語言中數組和指標總有千絲萬縷的聯絡。表現在以下幾個方面
一 數組名同時也是該數組首元素的地址
對於數組f[MAX]有 f==&f[0]
&運算子取得數組元素f[0]的記憶體位址,因此f和&f[0]都是常量且相等
二 可以使用指標處理數組
若p[MAX]是一個數組,其首地址為0x00000000那麼p+1的值是0x00000001嗎?
回答是不一定。因為對一個指標加上1結果是對該指標增加一個儲存單元。對於數組地址會增加到下一個元素的首地址,而不一定是一個位元組。那麼p和p+1之間到底相差多少呢?這要有p所指對象的類型來決定。如果數組的類型是type那麼p與p+1相差 sizeof(type)個位元組。
總結: 1 指標的數值就是它所指向的對象的地址,地址的內部表示由硬體決定。
2 對指標加1等價於對指標的值加上它指向對象的位元組大小。
c 語言標準描述數組時,藉助了指標的概念,例如a[n]的意思是*(a+n),即先定址到記憶體中的a,然後移動n個單位,再取出該記憶體處的值。
因此 p+2==&p[2], *(p+2)==p[2]
在這裡要區分 *(p+2)和*p+2的不同。由於*運算子的優先順序比+要高, *(p+2)得到的是數組p中第三個元素的值。 *P+2得到的是數組p中第一個元素的值與2相加後的結果。
三 指標數組和指向數組的指標
int *p[3]和 int (*p)[3]有什麼區別呢?
1 []的優先順序高於* 因此int *p[3]等價於int *(p[3])括弧內顯然是一個數組,括弧外的部分表明了數組p的類型,因此p是一個含有3個元素的數組,數組的每一個元素是一個指標,而且是指向int型變數的指標。
2 int (*p)[3]使得指標p指向了一個包含有3個元素的數組,該數組中元素類型為int。 可以用下面的方法記憶
int *p ;
int a;
p= &a;
*p=a;
因此(*p)用a代替,從字面上看int(*p)[3]替換為int a[3] ,故可以理解p指向了a[3]。
四 指標和多維陣列
int zippo[4][2]; /*整數數組的數組*/
數組名 zippo是數組首元素的地址 zippo的首元素本身又是包含兩個int型變數的數組。
zippo得值和&zippo[0]相同,而 zippo[0]的值同其首元素的地址&zippo[0][0]
相同。zippo[0]是一個整數大小的地址,而zippo是兩個整數大小對象的地址。
對一個指標加1,會對原來的數值加上一個對應類型大小的數值。在這方面zippo和zippo[0]是不一樣的。zippo所指的對象是兩個int,而zippo[0]所指的對象是一個int
對一個指標取值得到的是該指標所指對象的數值
*(zippo[0]) 代表格儲存體在zippo[0][0]中的數值,即一個int值
*zippo 代表其首元素zippo[0]的值,但zippo[0]本身就是一個int數的地址即 &zippo[0][0],所以 *zippo 就是 &zippo[0][0], **zippo <=> *&zippo[0][0] <=> zippo[0][0]
變長數組
一 聲明變長數組
C99標準引入變成數組,它允許使用變數定義數組維數
變長數組有一些限制,變長數組必須是自動儲存類的,這意味著他們必須在函數內部或作為函式宣告且聲明時不可以進行初始化。
樣本: int m=2,n=3;
int a[m][n];
這裡a是一個二維數組。
“變長”的意思是指在程式運行時動態建立不同維數的數組,而每一次建立以後該數組就是固定大小的,知道其生存期結束。
二 變長數組作為函數參數
由於變長數組維數在運行時確定,故將其作為函數參數可以提高程式的靈活性和適應性。
聲明一個帶變長數組參數的函數
int sum (int rows, int cols, int ar[rows][cols]);
註: ar的聲明中使用了rows和cols,所以在參數列表中對rows和cols的聲明要早於ar。
C99標準規定可以省略函數原型中的名稱,但如果省略名稱,則需要用星號代替省略的維數。 例如 int sum (int rows, int cols, int ar[*][*]);