2012-05-31 42 views
58

例如,如果somestruct有三個整數成員,我一直認爲這是行執行此操作在C(或C++)函數:C和C++:自動結構的部分初始化

somestruct s = {123,}; 

第一成員將初始化爲123,最後兩個將初始化爲0.我經常對自動數組做同樣的事情,編寫int arr[100] = {0,};,以便將數組中的所有整數初始化爲零。

如果你不初始化結構變量,其效果取決於 無論是有靜態存儲(請參閱存儲類型說明符)或 不是:


最近我的GNU C Reference Manual讀取。如果是,則具有整數類型的成員將初始化爲0,並且 指針成員將初始化爲NULL;否則, 結構的成員的值是不確定的。


是否有人可以告訴我的C和C++標準說,關於部分自動結構和自動初始化數組是什麼?我在Visual Studio中做了上面的代碼,沒有問題,但我想兼容gcc/g ++,也可能是其他編譯器。由於

+1

對於C++ - 問題的一部分,[這個問題](http://stackoverflow.com/questions/1613341/)可能會讓你感興趣。 –

回答

84

鏈接的GCC文檔不說話部分初始化它只是(完成)初始化沒有初始化的會談。

什麼是部分初始化?

的標準沒有定義對象的初始化部分,無論是有完整的初始化或不初始化。部分初始化是一種非標準術語,它通常指的是您提供了一些初始化程序的情況,但不是全部:即初始化程序比數組大小或初始化結構元素的數量少。

例子:

int array[10] = {1,2};     //Case 1:Partial Initialization 

什麼是(完成)初始化或沒有初始化?

初始化意味着爲正在創建的變量同時創建一些初始值。即:在相同的代碼語句中。

例子:

int array[10] = {0,1,2,3,4,5,6,7,8,9}; //Case 2:Complete Initialization 
int array[10];       //Case 3:No Initialization 

的引用的段落描述了Case 3的行爲。

有關部分初始化(Case 1)的規則由標準定義,並且這些規則不取決於正在初始化的變量的存儲類型。AFAIK,所有主流編譯器都100%符合這些規則。


是否有人可以告訴我的C和C++標準說,關於部分自動結構和自動初始化數組是什麼?

C和C++標準保證即使一個整數陣列位於自動存儲,如果有在大括號內的列表更少初始化然後未初始化元件必須被初始化爲0

C99標準6.7.8.21

如果在一個大括號內的列表更少初始化以外還有用於初始化一個數組元素或聚集體的成員,或更少的字符在字符串文字已知大小的數組比數組中的元素多,其餘的聚合將被隱式地初始化爲具有靜態存儲持續時間的對象。


在C++中的規則與一個小差別說明。

C++ 03標準8.5.1骨料
帕拉7:

如果在列表中更少的初始化值多於在聚集構件,則每個部件不明確的初始化應爲初始化值(8.5)。 [實施例:

struct S { int a; char* b; int c; }; 
S ss = { 1, "asdf" }; 

初始化ss.a1ss.b"asdf",和ss.c與表單int()的表達式的值,即,0。 ]

雖然正值初始化被定義在,
C++ 03 8.5初始化器
第5段:

值初始化類型T的對象是指:
- 如果T是具有用戶聲明的構造函數的類類型(第9節)1),那麼T的默認構造函數被調用(並且如果T沒有可訪問的默認構造函數,則初始化是不合格的);
- 如果T是一個沒有用戶聲明構造函數的非聯合類類型,那麼T的每個非靜態數據成員和基類組件都進行了值初始化;
- 如果T是一個數組類型,那麼每個元素都進行了值初始化;
- 否則,該目的是零初始化

+0

謝謝你這個徹底的答案。關於值初始化,你碰巧知道在C++中DWORD()形式的表達式是否保證爲0? Björn對我的問題發表了評論,並將一個關於值初始化的問題聯繫起來,但我不清楚Visual Studio是否支持這個問題,因爲它是C++ 98而不是C++ 03。 – loop

+0

@test:AFAIK,在C++ 98中,只有兩種類型的初始化,*零初始化*和*默認初始化*,C++ 03添加*值初始化*,'在DWORD()'在C + + 98被評估爲*零初始化*。 –

+0

好的再次感謝 – loop

0

如果變量是全局和靜態,它在其中被初始化爲零的二進制全局區分配。 如果變量是本地的,它的堆棧分配,編譯器不會在堆棧初始化的內存。(有的調試版本可以初始化,但發行版本從來沒有做到這一點),如果變量是在堆中分配

中,編譯器也不會初始化它。

15

在C中,對象是從來沒有部分初始化 - 如果它們的任何部分被初始化,則整個對象(以及所有子對象遞歸地)被初始化。如果沒有提供明確的初始化程序,則將元素初始化爲「適當類型的零」。

您問題中的引用是指當整個對象的初始化程序完全被忽略時,而不是當子對象缺少初始化程序時。例如,假設arr具有自動存儲持續時間,則這樣的:

int arr[100] = { 123 }; 

初始化arr[0]123arr0所有其他元素。鑑於此:

int arr[100]; 

使arr的每個元素都未初始化。這是後面的情況,引用是引用。

4

最新版本的GCC還允許「部分」初始化,並在同一時間zeromem:現在

typedef struct{ 
    int a,b,c; 
}T; 

T s = {0, .b=5}; 

的結構成員將是這些值:a=0, b=5, c=0

我沒有任何信息其他編譯器是否允許這樣做:p

+3

這是一個C99功能,並不是特別新穎。它被稱爲「指定初始化程序」並得到廣泛支持。不過這不是C++特性。 C++使用構造函數。 – MSalters

0
// You can use something like this: 
typedef struct { 

    ...; 

    ...; 

} somestruct; 

// Declaration of struct 
somestruct st; 

// Initialising with 0. It does not depend on the size of the 
// structure and the number of elements in it. 
// memset() initialisation doesn't care if struct is static or dynamic. 
// but don't forget to use st instead &st to dynamic. 
memset(&st, 0, sizeof(somestruct));