簡體   English   中英

為什么允許命名嵌套結構?

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

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