1. 程式人生 > >C語言的陣列初始化

C語言的陣列初始化

    這是很基礎的東西,但基礎的重要性不言而喻,我敢肯定這個知識點我肯定曾經瞭解過,但現在,我不敢確定,由此可見紀錄的重要性,這世界沒有什麼捷徑,找對方向,然後不停重複.所以從今天開始,我會比較詳細的紀錄這些比較小的知識點,其實還是有不少有意思的地方的.


    寫這篇文章的起因在於<<COM技術內幕>>第七章新東西太多,看的我目不暇接,所以在網上找了些例子看,其中就有一個例子中出現了這樣的語句: 

...
wchar_t wname[
128]={0};
char cname[256]={0};
...

我感興趣的是:
1.這種賦值的結果.
2.這種形式是否符合標準編碼規則?

我找到了如下資料,可能有助於對這個知識點的掌握.

/*
初始化值的個數可少於陣列元素個數.當初始化值的個數少於陣列元素個數時,前面的按序初始化相應值, 後面的初始化為0(全域性或靜態陣列)或為不確定值(區域性陣列).
*/

我相信上面的資料是C和C++語言的標準規範,但實際編譯器處理時,可能會和規範有所不同.因為編譯器原則上要遵從語言規範,但對於區域性陣列的不確定值到底是多少,怎麼處理,編譯器就可以靈活處理.我測試了三種編譯器,其實編譯器賦予的值是固定的,都是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";

*/

下面來看一個例子:

#include <iostream.h>

int array1[5]={1,2,3};
staticint array2[5]={1};


void main()
{
    
int arr1[5]={2};
    
staticint arr2[5]={1,2};
    
    
int n;
    cout 
<<"global: ";
    
for(n=0; n<5; n++)
        cout 
<<""<<array1[n];
    
    cout 
<<" global static: ";
    
for(n=0; n<5; n++)
        cout 
<<""<<array2[n];
    
    cout 
<<" local: ";
    
for(n=0; n<5; n++)
        cout 
<<""<<arr1[n];
    
    cout 
<<" local static: ";
    
for(n=0; n<5; n++)
        cout 
<<""<<arr2[n];
    cout 
<<endl;
}


在這個例子中,全域性和靜態陣列都按語言規範要求被初始化為0,但是區域性陣列並沒有向前面所說的為不確定值,下面是用gcc,VC6.0,tuborC++分別編譯的結果(注意gcc用g++編譯c++檔案,gcc不會連結庫的):

/*
GCC 可同時用來編譯 C 程式和 C++ 程式。一般來說,C 編譯器通過原始檔的字尾名來判斷是 C 程式還是 C++ 程式。在 Linux 中,C 原始檔的字尾名為 .c,而 C++ 原始檔的字尾名為 .C 或 .cpp。
    但是,gcc 命令只能編譯 C++ 原始檔,而不能自動和 C++ 程式使用的庫連線。因此,通常使用 g++ 命令來完成 C++ 程式的編譯和連線,該程式會自動呼叫 gcc 實現編譯。
*/

GCC:

VC6.0:


TurboC++

    這說明了對區域性陣列沒有初始化的元素的值,這幾種編譯器都將其設定為0.但是,如果如果不對陣列進行初始化,即在定義的同時沒有用列表初始化,那麼區域性陣列的值就取決於編譯器而對程式設計師來說就是不可預料的了.有時間可以測試一下各個編譯器,不過在vc中是0xcc.所以對區域性陣列的初始化要特別小心.但是全域性的陣列和靜態陣列還是會被正確的賦於0值的.

    在VC的安裝盤的/VC98/CRT下可以看到vc自帶的C/C++庫的原始碼.