分享方式:


解譯更複雜的宣告子

您可以將任何宣告子括在括弧中,以指定「複雜宣告子」的特定解譯。複雜宣告子是由多個陣列、指標或函式修飾詞限定的識別碼。 您可以將各種不同的陣列、指標及函式修飾詞組合套用至單一識別項。 通常可使用 typedef 簡化宣告。 請參閱 Typedef 宣告

在解譯複雜宣告子時,方括號和括號 (即在識別項右邊的修飾詞) 的優先順序高於星號 (即在識別項左邊的修飾詞)。 方括號和括號的優先順序相同,並且都是由左至右關聯。 在完整解譯宣告子之後,會在最後一個步驟套用類型指定名稱。 您可以使用括號覆寫預設的關聯順序並強制執行特定解譯。 但是,請勿使用括號括住識別項名稱本身。 否則,會被錯誤解譯為參數清單。

解譯複雜宣告子的一個簡單方式是透過下列四個步驟「從內而外」進行讀取:

  1. 從識別項開始,直接尋找方括號或括號 (如果有的話) 的右方。

  2. 解譯這些方括號或括號,然後在左方尋找星號。

  3. 如果您在任何階段遇到右括號,請返回並將規則 1 和 2 套用到括號內的所有內容。

  4. 套用類型指定名稱。

    char *( *(*var)() )[10];
     ^   ^  ^ ^ ^   ^    ^
     7   6  4 2 1   3    5
    

在本範例中,步驟是依序編號,並可解譯為如下:

  1. var 識別項宣告為

  2. 指標指向

  3. 函式傳回

  4. 指標指向

  5. 10 個元素的陣列,包括

  6. 其指標

  7. char 值。

範例

下列範例說明其他複雜宣告,並示範括號如何影響宣告的意義。

int *var[5]; /* Array of pointers to int values */

陣列修飾詞的優先順序高於指標修飾詞,因此會將 var 宣告為陣列。 指標修飾詞套用至陣列元素的類型;因此,陣列元素是 int 值的指標。

int (*var)[5]; /* Pointer to array of int values */

在此 var 宣告中,指標修飾詞加了括號,因此優先順序高於陣列修飾詞,而 var 則被宣告為五個 int 值之陣列的指標。

long *var( long, long ); /* Function returning pointer to long */

函式修飾詞的優先順序也高於指標修飾詞,因此這個宣告會 var 宣告 var 為傳回值的指標 long 的函式。 函式宣告為接受兩 long 個值做為引數。

long (*var)( long, long ); /* Pointer to function returning long */

這個範例與上一個範例類似。 括弧會將指標修飾詞的優先順序高於函式修飾詞,並 var 宣告為傳回 long 值的函式指標。 同樣地,函式會採用兩個 long 引數。

struct both       /* Array of pointers to functions */
{                 /*   returning structures         */
    int a;
    char b;
} ( *var[5] )( struct both, struct both );

陣列的元素不可為函式,不過,這個宣告會示範如何將指標陣列改宣告為函式。 在此範例中,var 會宣告為有五個指標之陣列,且此陣列屬於傳回有兩個成員之結構的函式。 函式的引數會宣告為兩個相同結構類型 (both) 的函式。 請注意,*var[5] 一定要加上括號。 如果不加括號,宣告即為無效的函式陣列宣告,如下所示:

/* ILLEGAL */
struct both *var[5](struct both, struct both);

下列陳述式會宣告指標陣列。

unsigned int *(* const *name[5][10] ) ( void );

name 陣列會將 50 個元素歸納在多維陣列中。 這些元素是本身為常數之指標的指標。 這個常數指標會指向沒有參數的函式,而且傳回不帶正負號類型的指標。

下一個範例是傳回三 double 個值陣列指標的函式。

double ( *var( double (*)[3] ) )[3];

在這個宣告中,由於傳回陣列的函式無效,因此函式會傳回陣列指標。 這裡 var 宣告為函式,傳回三 double 個值陣列的指標。 var 函式會採用一個引數。 引數就像傳回值一樣,是三 double 個值的陣列指標。 引數類型會由複雜的 abstract-declarator 指定。 需要引數類型中星號周圍的括弧;如果沒有它們,引數類型會是值三個指標 double 的陣列。 如需抽象宣告子的討論和範例,請參閱抽象宣告子

union sign         /* Array of arrays of pointers */
{                  /* to pointers to unions       */
     int x;
     unsigned y;
} **var[5][5];

如上述範例所示,指標可以指向另一個指標,而且陣列可以包含作為元素的陣列。 在這裡,var 是有五個元素的陣列。 每個項目都是五個元素陣列指標的指標與有兩個成員的等位。

union sign *(*var[5])[5]; /* Array of pointers to arrays
                             of pointers to unions        */

這個範例示範括號位置如何改變宣告的意義。 在此範例中,var 是等位五個元素陣列指標的五個元素陣列指標。 如需如何使用 typedef 避免複雜宣告的範例,請參閱 Typedef 宣告

另請參閱

宣告和類型