陣列,結構體初始化為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。
最後,總結下結構體初始化常用的2種方法
//////////////////////////////////////////////////////////////////////////////////////////////
struct{
//...
int a;
int *p;
}x;
memset(&x, 0, sizeof(x))
或者
memset(&x, 0, sizeof(struct A_stru))
這是結構體變數初始化為0的常見方法,需要注意x前的&號。
///////////////////////////////////////////////////////////////////////////////////////////////////
struct A a = {0};