1. 程式人生 > >陣列,結構體初始化 {0}

陣列,結構體初始化 {0}

 

一直以為 int a[256]={0};是把a的所有元素初始化為0,int a[256]={1};是把a所有的元素初始化為1.
除錯的時檢視記憶體發現不是那麼一回事,翻了一下《The C++ Programming Language》總算有定論。PDF的竟然不然複製,就把它這章翻譯了,如下

5.2.1  陣列初始化
陣列可以用一個列值來初始化,例如
        int v1[] ={1,2,3,4};
        char v2[]={'a','b','c',0};
當陣列定義時沒有指定大小,當初始化採用列表初始化了,那麼陣列的大小由初始化時列表元素個數決定。所以v1和v2分別為 int[4] 和char[4]型別。如果明確指定了陣列大小,當在初始化時指定的元素個數超過這個大小就會產生錯誤。例如:
        char  v3[2] ={'a','b',0};  //錯誤:太多的初始化值了
        char  v3[3] ={'a','b',0};  //正確

如果初始化時指定的的元素個數比陣列大小少,剩下的元素都回被初始化為  0。例如
        int  v5[8]={1,2,3,4};
等價於
         int  v5[8]={1,2,3,4,0,0,0,0};

注意沒有如下形式的陣列賦值:
        void f()
        {
            v4={'c','d',0};  //錯誤:不是陣列賦值
        }
如果你想這樣的複製的話,請使用vector(16章第三節) 或者valarray(22章第四節)。
       字元陣列可以方便地採用字串直接初始化(參考第五章 2.2小節)
        譯註: 就是 這樣啦  char  alpha []="abcdefghijklmn";

The C++ Programming Language ,Third Edition by Bjarne Stroustrup.

、、、、、、、、、、、、、、、、、、、、、、、、、、、///////

/////////////////////////////////////////////////////////////

6.6   集合初始化
顧名思義,集合(aggregate)就是多個事物聚集在一起,這個定義包括混合型別的集合:像struct和class等,陣列就是單一型別的集合。
初始化集合往往既冗長又容易出錯,而C++中集合初始化(aggregate  initialization)卻變得很方便而且很安全。當產生一個集合物件時,要做的只是指定初始值就行了,然後初始化工作就由編譯器去承擔了。這種指定可以用幾種不同的風格,它取決於正在處理的集合型別。但不管是哪種情況,指定的初值都要用大括號括起來。比如一個內部型別的陣列可以這樣定義:
int  a[5]  =  {  1,  2,  3,  4,  5  };
如果給出的初始化值多於陣列元素的個數,編譯器就會給出一條出錯資訊。但如果給的初始化少於資料元素的個數,那將會怎麼樣呢?例如:
int  b[6]  =  {0};
這時,編譯器會把第一個初始化值賦給陣列的第一個元素,然後用0賦給其餘的元素。注意,如果定義了一個數組而沒有給出一列初始值時,編譯器並不會去做初始化工作。所以上面的表示式是將一個數組初始化為零的簡潔方法,它不需要用一個for迴圈,也避免了“偏移1位”錯誤(它可能比for迴圈更有效,這取決於編譯器)。
陣列還有一種叫自動計數(automatic  counting)的快速初始化方法,就是讓編譯器按初始化值的個數去決定陣列的大小:
int  c[  ]  =  {  1,  2,  3,  4  };
現在,如果決定增加另一個元素到這個陣列上,只要增加一個初始化值即可,如果以此建立我們的程式碼,只需在一處作出修改即可。這樣,在修改時出錯的機會就減少了。但怎樣確定這個陣列的大小呢?用表示式sizeof  c  /  sizeof  *c(整個陣列的大小除以第一個元素的大小)即可算出,這樣,當陣列大小改變時它不需要修改。
for  (  int  i  =  0;  i  <  sizeof  c  /sizeof  *c;  i++)
c[i]++;
因為結構也是一種集合型別,所以它們也可以用同樣的方式初始化。因為C風格的struct的所有成員都是public型的,所以它們的值可以直接指定。
struct  X  {
int  i;
float  f;
char  c;
};
X  x1  =  {  1,  2.2,  ‘c’  };
如果有一個這種struct的陣列,也可以用巢狀的大括號來初始化每一個物件:
X  x2[3]  =  {  {1,  1.1,  ‘a’},  {2,  2.2,  ‘b’}};
這裡,第三個物件被初始化為零。
如果struct中有私有成員(典型的情況就是C++中設計良好的類),或即使所有成員都是公共成員,但有建構函式,情況就不一樣了。在上例中,初始值被直接賦給了集合中的每個元素,但建構函式是通過正式的介面來強制初始化的。這裡,建構函式必須被呼叫來完成初始化,因此,如果有一個下面的struct型別:
struct  Y  {
float  f;
int  i;
Y(int  a);
};
必須指示建構函式呼叫,最好的方法像下面這樣:
Y  y1[  ]  =  {  Y(1),  Y(2),  Y(3)  };
這樣就得到了三個物件和進行了三次建構函式呼叫。只要有建構函式,無論是所有成員都是公共的struct還是一個帶私有成員的class,所有的初始化工作都必須通過建構函式來完成,即使正在對一個集合初始化。
下面是多建構函式引數的又一個例子:
//:  C06:Multiarg.cpp
//  From  Thinking  in  C++,  2nd  Edition
//  Available  at  http://www.BruceEckel.com
//  (c)  Bruce  Eckel  2000
//  Copyright  notice  in  Copyright.txt
//  Multiple  constructor  arguments
//  with  aggregate  initialization
#include  <iostream>
using  namespace  std;

class  Z  {
  int  i,  j;
public:
  Z(int  ii,  int  jj);
  void  print();
};

Z::Z(int  ii,  int  jj)  {
  i  =  ii;
  j  =  jj;
}

void  Z::print()  {
  cout  < <  "i  =  "  < <  i  < <  ",  j  =  "  < <  j  < <  endl;
}

int  main()  {
  Z  zz[]  =  {  Z(1,2),  Z(3,4),  Z(5,6),  Z(7,8)  };
  for(int  i  =  0;  i  <  sizeof  zz  /  sizeof  *zz;  i++)
    zz[i].print();
}  ///:~
注意:這看起來就好象對陣列中的每個物件都呼叫顯式的建構函式。

、、、、、、、、、、、、

/////////////////////////////////////////////////////////

該問題涉及到資料型別初始化的問題,現將C語言中資料型別初始化總結如下

簡單變數的初始化形式如下: 資料型別 變數名=初始化值;
  例如,定義整型變數a,並給其初始化值10的語句如下
  int a=10;

陣列的初始化,需要通過一常量資料列表,對其陣列元素分別進行初始化,形式如下:
 資料型別 陣列名稱〔陣列長度〕={初始化值1,初始化值2,…, 初始化值n};

 例如,定義長度為5的整型陣列,並對其初始化的語句如下:
 int A[5]={20,21,0,3,4};

結構體變數的初始化方式與陣列類似,分別給結構體的成員變數以初始值,而結構體成員變數的初始化遵循簡單變數或陣列的初始化方法。具體的形式如下:
 struct 結構體識別符號
 {
   成員變數列表;
    …
 };
 struct結構體識別符號 變數名={初始化值1,初始化值2,…, 初始化值n };
 例如,定義struct Point型別變數,並初始化的語句如下:
 struct Point oP1={0.0,0.2,0.3};
 struct Point型別變數oP1的三個成員變數的值分別為
 oP1.x=0.0,
 oP1.y=0.2
 oP1.z=0.3
由於定義結構體變數有三種方法,因此初始化結構體變數的方法對應有三種,上面已經介紹了其中的一種形式,其他兩種形式如下:
struct Point
{
 double x;
 double y;
 double z;
} oP1={0.0,0.2,0.3}; struct
{
 double x;
 double y;
 double z;
} oP1={0.0,0.2,0.3};
在初始化結構體變數時候,既可以初始化其全部成員變數,也可以僅僅對其中部分的成員變數進行初始化。例如:
struct Student
{
 long id;
 char name[20];
 char sex;
}a= {0};
其相當於a.id=0;a.name=“”;a.sex=‘\0x0’。
僅僅對其中部分的成員變數進行初始化,要求初始化的資料至少有一個,其他沒有初始化的成員變數由系統完成初始化,為其提供預設的初始化值。各種基本資料型別的成員變數初始化預設值如表9-1所示。

資料型別
預設初始化值
Int                  0
Char               ‘\0x0’
float               0.0
double              0.0
char Array[n]       ”
int Array[n]        {0,0…,0}



對於複雜結構體型別變數的初始化,同樣遵循上述規律,對結構體成員變數分別賦予初始化值。例如:
struct Line
{
int id;
struct Point StartPoint;
struct Point EndPoint;
}oLine1={0,
{0,0,0},
{100,0,0}
};
其中常量0用於初始化oLine1的基本型別成員變數id;常量列表{0,0,0}用於初始化oLine1的struct Point型別成員變數StartPoint;常量列表{100,0,0}用於初始化oLine1的struct Point型別成員變數EndPoint。