[英]Excess elements of scalar initializer for pointer to array of ints
我正在 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}
};
但是編譯器會打印警告:標量初始值設定項中的元素過多。
將數組傳遞給函數時,谷歌搜索沒有幫助,甚至 K&R 寫入,
myFunction(int daytab[2][13]) {...}
是相同的
myFunction(int (*daytab)[13]) {...}
兩者只是部分等效。 不同之處在於:
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
,並且編譯器生成一個警告,讓您知道您已經指定了許多剛剛被丟棄的daytab
。 由於初始化程序中的第一個數字是0
,因此您只是以一種相當冗長的方式將daytab
設置為NULL
。
因此,如果您想進行此類初始化,請使用第一個版本——它會衰減為您在第二個版本中顯式聲明的指針類型,因此您可以以相同的方式使用它。 當您希望動態分配數組或獲取對已存在的另一個數組的引用時,需要帶有數組指針的第二個版本。
所以你可以這樣做:
static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;
ptr = arr;
...然后交替使用ptr
和arr
。 或這個:
static char (*ptr)[3] = NULL;
ptr = malloc(2 * sizeof(*ptr));
...獲得一個動態分配的二維數組(不是指向一維數組的指針數組,而是一個真正的二維數組)。 當然,在這種情況下它不會被初始化。
兩種變體的“等價”僅意味着二維數組,當它衰減到指向其第一個元素的指針時,衰減到第二個變體中聲明的指針類型。 一旦指針版本實際指向一個數組,兩者是等價的。 但是二維數組版本為數組設置了內存,其中指針聲明沒有......並且可以為指針分配一個新值(指向不同的數組),而二維數組變量則不能。
但是,在 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}
};
@Dmitri 解釋得很好,但我想補充一點
static char (*daytab)[13] = { ... };
是一個指向 13 個char
元素數組的指針。 編譯器向您發出警告,因為您傳入了兩個數組。 這就像嘗試將兩個地址分配給一個指針char *p = {a, b}
。 根據您的聲明,元素過多。 請參閱Geekforgeek對數組指針真正含義的解釋。
至於回答 K&R 練習,請考慮
選項1:
static char *daytab[2] = {
(char []) {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
(char []) {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};}
或選項 2:
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}
};}
選項 1 是一個包含兩個char
指針的數組。
選項 2 是一個數組指針。 它指向一個包含 13 個char
元素的數組。 就像你可以增加一個char
指針來獲取字符串中的下一個字母一樣,你可以增加這個數組指針來獲取下一個 13 個char
的數組。
我自己剛剛在 K&R 中解決了這個問題,所以也許我可以添加到已經給出的非常好的答案中。 這是擺脫使用二維數組而轉向使用指針數組的一個很好的練習。 請注意,在本書的這一點上,我們還沒有介紹malloc
。 因此,一種方法是預先設置月份數組,然后是指向這些數組的指針數組:
char y0[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char y1[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char *daytab[] = {y0, y1};
回想一下,數組的名稱是指向第一個元素的指針。 現在你真的有一個指向兩個 13 個int
數組的指針數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.