struct Figlio
{
char nome[256];
struct Genitore* padre;
struct Genitore* madre;
};
struct Genitore
{
char nome[256];
struct Figlio* progenie;
};
int main()
{
return 0;
}
我預計上面的代碼不會編譯,因為struct Genitore之前沒有宣告Figlio,所以需要前向宣告Genitore(即struct Genitore;在頂部)。相反,在 C 中,它可以毫無問題地編譯。
相反,如果我將尚未宣告的結構指標傳遞給函式,例如,
void f(struct st*);
struct st{};
它會引發以下警告
warning: ‘struct st’ declared inside parameter list will not be visible outside of this definition or declaration
所以,我不明白為什么這些不同的行為,特別是為什么不要求分別宣告struct Genitore;和宣告。struct st;
uj5u.com熱心網友回復:
這是一個范圍問題。
首先,關于標簽的規則, C 標準struct的第 6.2.1p7 節規定:
結構、聯合和列舉標記的范圍緊隨標記出現在宣告標記的型別說明符中之后開始。...
這就是允許struct標簽的出現在任何地方都充當宣告的原因。這也允許結構包含指向自身的指標并使其參考相同的型別。
那么識別符號范圍的規則在 6.2.1p4 節中列出:
每個其他識別符號的范圍由其宣告的位置決定(在宣告符或型別說明符中)。如果宣告識別符號的宣告符或型別說明符出現在任何塊或引數串列之外,則識別符號具有檔案范圍,它在翻譯單元的末尾終止。如果宣告識別符號的宣告符或型別說明符出現在塊內或函式定義中的引數宣告串列內,則識別符號具有塊作用域,它在關聯塊的末尾終止。如果宣告識別符號的宣告符或型別說明符出現在函式原型(不是函式定義的一部分)的引數宣告串列中,則識別符號具有函式原型范圍,它在函式宣告符的末尾終止。如果識別符號在同一名稱空間中指定兩個不同的物體,則范圍可能重疊。如果是這樣,一個物體的范圍(內部范圍)將嚴格在另一個物體的范圍(外部范圍)之前結束。在內部范圍內,識別符號指定在內部范圍內宣告的物體;在外部范圍內宣告的物體在內部范圍內隱藏(不可見)
請特別注意兩個加粗的段落。struct Genitore將指向該型別的指標宣告為具有檔案范圍的成員時的隱式宣告struct Figlio,因為它沒有出現在塊陳述句中,也沒有出現在函式宣告中,因此從該點開始在源檔案中是可見的。
相反,出現在函式宣告中的隱式宣告僅在宣告本身的范圍內。這樣的型別宣告是有問題的,因為您傳入的任何潛在結構指標都將參考與函式宣告中隱式宣告的型別不同的型別。
uj5u.com熱心網友回復:
在這份宣告中
struct Figlio
{
char nome[256];
struct Genitore* padre;
struct Genitore* madre;
};
您宣告了兩個指向不完整型別的指標struct Genitore。
指標型別是完整的物件型別。
也就是說,在這些宣告中,您宣告struct Genitore了指標型別的不完整型別和物件struct Genitore *。
結構型別的宣告在宣告結構struct Genitore的范圍內可見Figlio(在檔案范圍或塊范圍內)
另一個引入不完整結構型別的例子是在 typedef 宣告中宣告 it
typedef struct A A;.
您可以在同一范圍內的 typedef 宣告之后的某處定義結構。
另一個例子是在函式宣告的回傳型別中宣告結構不完整型別。例如
struct A f( void );
同樣,您至少需要在函式定義之前或函式呼叫之前定義結構。
這是一個演示程式。
#include <stdio.h>
struct A f( void );
struct A { int x; } f( void )
{
struct A a = { .x = 10 };
return a;
};
int main( void )
{
struct A a = f();
printf( "a.x = %d\n", a.x );
}
程式輸出為
a.x = 10
另一方面,如果您嘗試取消參考指向不完整型別的指標,編譯器將發出錯誤。
在這份宣告中
void f(struct st*);
型別說明符struct st具有函式原型范圍,并且在函式引數串列之外不可見。
來自 C 標準(6.2.1 識別符號范圍)
- ...如果宣告識別符號的宣告符或型別說明符出現在函式原型(不是函式定義的一部分)的引數宣告串列中,則識別符號具有函式原型范圍,該范圍終止于函式宣告符的末尾。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/456705.html
