[英]Why are named nested structure allowed?
我偶然發現了C的一個非常奇怪的功能:您可以在另一個結構中聲明一個命名結構,只要該結構同時聲明該類型的成員變量:
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st { /* <- named struct */
int capacity;
int load;
} battery;
};
然后,內部結構可以像其他任何類型一樣在結構外部使用,從而呈現出像這樣完全有效的奇怪代碼:
struct Robot_st my_robot = {2, 3, {200, 50}};
struct BatteryStatus_st battery_snapshot; /* <- use of inner struct */
memcpy(
&battery_snapshot,
&my_robot.battery,
sizeof(struct BatteryStatus_st)
);
printf("robot position: %d,%d\n", my_robot.pos_x, my_robot.pos_y);
printf("battery load: %d%%\n", battery_snapshot.load);
嵌套未命名的結構感覺不錯,因為以后您無法訪問類型時,就不會對類型的范圍感到困惑。 上面的代碼在C ++中也是無效的,盡管嵌套聲明是有效的,因為C ++將其理解為外部結構名稱空間中的類型,因此您需要使用
struct Robot_st::BatteryStatus_st battery_snapshot;
盡管同時聲明一個類型和一個成員感到很奇怪,但這更有意義。
那么,為什么這種構造在C語言中有效呢? 背后是否有任何歷史/原因? 有這種結構的用例嗎? (我的錯誤是導致失敗的錯誤,因此是問題。)
除了其他兩個答案,這是一個真正的用例,它需要這樣的命名內部結構:
struct LinkedList {
//data members stored once per list
struct LinkedListNode {
//data members for each entry of the list
struct LinkedListNode *next;
} *head, *tail;
};
很難為鏈接列表的結構寫出更簡潔的定義。
無法命名的內部結構將無法使用:將某些內容插入鏈表的代碼可能必須使用節點指針聲明局部變量。 而且,在鏈表結構之外聲明節點結構毫無意義。
最初在C中允許使用此類構造,因為結構名稱完全占據了自己的整個Universe,從來沒有對其應用任何范圍界定規則[順便說一下,結構成員名稱也具有這種作用域,這就是為什么舊標准庫中的某些結構類型的原因其成員上帶有前綴]。 因為存在一些代碼,它們以與作用域不一致的方式使用結構名稱,所以在不破壞現有代碼的情況下,無法更改標准以禁止這種用法。 雖然有時候值得破壞現有代碼(例如,擺脫C語言稱為gets
的可憎性),但這確實不是其中之一。
假設我具有以下結構:
struct OuterStruct
{
int a;
struct InnerStruct
{
int i;
int j;
} b;
} s;
現在,我可以訪問sa
,甚至可以將其保存在變量中,以更好地處理它,並將其傳遞給函數,...
int sa = s.a;
好吧,現在我想對sb
進行同樣的操作,為此,我需要InnerStruct
來命名!
???? sb = s.b; // here I have to use InnerStruct, otherwise sb would have no valid type!
另一種方法是申報InnerStruct
以外OuterStruct
,然后把它的一個實例內作為構件OuterStruct
。 但這掩蓋了InnerStruct
屬於OuterStruct
的事實,使您的意圖不太清楚。
好吧,這在C語言中是合法的:
struct BatteryStatus_st {
int capacity;
int load;
};
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st battery;
};
並且,正如您所指出的,它實際上與您發布的代碼相同(因為C沒有C ++中引入的名稱空間/作用域規則)。
如果將“內部”類型移入內部不會改變任何東西,但是有時可以澄清意圖,則禁止它似乎很奇怪。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.