簡體   English   中英

指向整數數組的指針的標量初始值設定項的多余元素

[英]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;

...然后交替使用ptrarr 或這個:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM