陣列、結構體的初始化
一直以來,初始化變數和陣列常採用定義時賦值的方法,今天在定義一個結構體的時候發現了一些問題,查了下相關資料發現以往的使用確實有些誤區,一直沒有注意到,於是蒐集了下零散的資料在此記錄一下。
一、以往常用的初始化方式:
1 int a=0; /*a初始化為0*/ 2 int b[10]={0}; /*b中全部元素初始化為0*/
想必一直這樣使用也確實不會發現問題,按照慣性思維,把0換成1就是把全部元素初始化為1了!然而事實卻並非如此,請看下面這段程式碼↓
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int a=1; /*a初始化為1*/ 9 int b[10]={1}; /*b中全部元素被初始化為1?*/ 10 printf("a=%d\n",a); 11 for(a=0;a<10;a++) 12 { 13 printf("b[%d]=%d\n",a,b[a]); 14 } 15 return 0; 16 }
這段程式的輸出結果如下↓
1 /* 2 a=1 3 b[0]=1 4 b[1]=0 5 b[2]=0 6 b[3]=0 7 b[4]=0 8 b[5]=0 9 b[6]=0 10 b[7]=0 11 b[8]=0 12 b[9]=0 13 Press any key to continue 14 */
可以看到,b陣列中的元素只有b[0]被初始化為了1,其餘元素依然為0。
通過查閱相關資料《The C++ Programming Language》,找到了以下內容:
5.2.1 陣列初始化
陣列可以用一個列值來初始化,例如
1 int v1[] ={1,2,3,4}; 2 char v2[]={'a','b','c',0};
當陣列定義時沒有指定大小,當初始化採用列表初始化了,那麼陣列的大小由初始化時列表元素個數決定。所以v1和v2分別為 int[4] 和char[4]型別。如果明確指定了陣列大小,當在初始化時指定的元素個數超過這個大小就會產生錯誤!例如:
1 char v3[2] ={'a','b',0}; //錯誤:太多的初始化值了 2 char v3[3] ={'a','b',0}; //正確
如果初始化時指定的的元素個數比陣列大小少,剩下的元素都回被初始化為 0 !
例如:
1 int v5[8]={1,2,3,4};
等價於
1 int v5[8]={1,2,3,4,0,0,0,0};
注意沒有如下形式的陣列賦值:
1 void f() 2 { 3 v4={'c','d',0}; //錯誤:不是陣列賦值 4 }
如果你想這樣的複製的話,請使用 vector(16章第三節) 或者 valarray(22章第四節)。
字元陣列可以方便地採用字串直接初始化(參考第五章 2.2小節)
譯註: 就是 這樣啦 char alpha []="abcdefghijklmn";
看完上述內容想必已經清楚的知道了陣列應該怎樣進行初始化了,此書在第六章還提及了結構體型別的的初始化問題,由於內容有過多重複,本文只列出重點。
二、集合的初始化
什麼是 集合:顧名思義,集合(aggregate)就是多個事物聚集在一起,這個定義包括混合型別的集合:像struct和class等,陣列就是單一型別的集合。
1、常見陣列即為一種集合,此處做一個小總結:
1>為陣列各個元素指定初值:
1 int a[5]={ 1, 2, 3, 4, 5};
2>如果給出的初始化值多於陣列元素的個數,編譯器就會給出一條出錯資訊。但如果給的初始化少於資料元素的個數,那將會怎麼樣呢?例如:
1 int b[6] = {0};
這時,編譯器會把第一個初始化值賦給陣列的第一個元素,然後用0賦給其餘的元素。注意,如果定義了一個數組而沒有給出一列初始值時,編譯器並不會去做初始化工作。所以上面的表示式是將一個數組初始化為零的簡潔方法,它不需要用一個for迴圈,也避免了“偏移1位”錯誤(它可能比for迴圈更有效,這取決於編譯器)。
3>陣列還有一種叫自動計數(automatic counting)的快速初始化方法,就是讓編譯器按初始化值的個數去決定陣列的大小:
1 int c[ ] = { 1, 2, 3, 4 };
4>對於二維陣列,可以看做多個一維陣列組成的集合,使用用巢狀的大括號 {{a[0]},{a[1]},{a[2]},…,{a[n-1]}} 來初始化其中的每個一維陣列,更高維陣列也是如此。
1 int a[3][2]={{1,1},{2,3},{3,6}};
2.關於struct關鍵字:
在C語言中,struct作為結構體宣告的關鍵字,不具備C++中類的功能,而在C++中,struct與class都可用做類關鍵字,區別在於struct類預設public,class類預設private,因此此處只介紹C語言中struct結構體的相關內容,C++中struct類可參考class部分。
因為結構也是一種集合型別,所以它們也可以用同樣的方式初始化。
1>定義一個普通結構體型別X:
1 struct X 2 { 3 int i; 4 float f; 5 char c; 6 };
使用X建立物件時,可以這樣初始化其每個成員的值:
1 X x1 = { 1, 2.2, 'c' };
使用X來建立物件陣列時,可以用巢狀的大括號 {{obj 1},{obj 2},{obj 3},…,{obj n}} 來初始化每一個物件:
1 X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'}};
這裡只列出了兩個物件的初值,所以第三個物件中的資料成員分別被初始化為對應資料型別的預設初值①
2>對於包含陣列的結構體來說,初始化與上述類似,需要說明的一點是,當陣列成員在結構體中定義在首位且給出不完全初始化表的情況下,初值是按照 陣列的元素順序 + 之後的成員表 依次被賦初值的,此處舉例說明:
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 struct Y 7 { 8 int i[2]; 9 float f; 10 char c; 11 }; 12 13 int main() 14 { 15 Y yy={1}; 16 Y y[3] = {1,2,3}; 17 printf("%d %d %f #%c#%d#\n", yy.i[0], yy.i[1], yy.f, yy.c, yy.c); 18 /*輸出結果:1 0 0.000000 # #0# */ 19 printf("%d %d %f\n", y[0].i[0], y[0].i[1], y[0].f); 20 /*輸出結果:1 2 3.000000 */ 21 printf("%d %f #%d#\n", y[2].i[0], y[2].f, y[2].c); 22 /*輸出結果:0 0.000000 #0# */ 23 return 0; 24 }
對於更復雜結構體也是如此,用{}逐級表明賦值關係即可。
3.關於class類
C++最主要的類的使用還用說嘛!!!不會的自己去看課本,去看建構函式和靜態成員的相關內容!!!╭(╯^╰)╮
三、補充
①各種資料型別的預設初值表
1 資料型別 預設初始化值 2 3 int 0 4 char '\0x0' 5 float 0.0 6 double 0.0 7 char Array[n] "" 8 int Array[n] {0,0,…,0}