2011-11-12 55 views
23

我正在練習以K & R(前5-9)和我的陣列努力的多餘的元素,整數

static char daytab[2][13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 
原程序的二維數組轉換

成使用指針來的13個整數的數組像

static char (*daytab)[13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

但是編譯器打印警告:在標量初始化過量的元素。

谷歌搜索沒有幫助甚至ķ&ř傳遞數組給一個函數時寫入,

myFunction(int daytab[2][13]) {...} 

相同

myFunction(int (*daytab)[13]) {...} 

回答

25

兩個只是部分等效。不同之處在於:

static char daytab[2][13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

聲明瞭一個二維陣列,包括設置預留陣列空間和確保daytab引用該內存。但是:

static char (*daytab)[13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

...只聲明一個指針。所以你試圖用一個數組初始值設定項來初始化一個指針,它不能按預期工作。沒有數組;沒有爲陣列留出任何內存。相反,您的初始化程序中的第一個數字將被分配給指針daytab,並且編譯器會生成一條警告,通知您已經指定了許多隻是被丟棄的附加值。由於初始化程序中的第一個數字是0,因此您只需以相當詳細的方式將daytab設置爲NULL即可。

所以如果你想做這種初始化,使用第一個版本 - 它會衰減到你在第二個版本中顯式聲明的相同指針類型,所以你可以用同樣的方法。如果您希望動態分配數組或獲取對已存在的另一個數組的引用,則需要使用數組指針的第二個版本。

所以,你可以這樣做:

static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; 
static char (*ptr)[3] = NULL; 

ptr = arr; 

...然後使用ptrarr互換。或者這樣:

static char (*ptr)[3] = NULL; 

ptr = malloc(2 * sizeof(*ptr)); 

...得到一個動態分配的二維數組(不是指針,以一維數組的數組,而是一個真正的二維數組)。當然,在這種情況下它不會被初始化。

這兩個變體的「等價」僅僅意味着二維數組,當它衰減到指向其第一個元素的指針時,會衰減到第二個變體中聲明的指針類型。一旦指針版本實際指向一個數組,兩者是等價的。但是二維數組版本爲數組設置內存,其中指針聲明不會......並且可以爲2D數組變量所不能指向的指針指定一個新值(指向另一個數組)。

在C99可以做到這一點,但(如果不是static至少):

char (*daytab)[13] = (char [][13]){ 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 
+0

堆棧空間?如果它是靜態的,那麼它會進入數據部分。 –

+0

@BrianGordon更正了...我在輸入那個部分的時候忘記了「靜態」(我認爲......很久以前)。 – Dmitri

+0

然後可以像這樣訪問指針'(*(daytab + leap))[i]'(關於練習) – Vladimir