2017-10-17 152 views
2

我看到this way在C11中實現某種struct繼承與匿名struct,並且想試用它。以下是我有:從GCCC11結構繼承與匿名結構

struct struct_a { 
    int aa; 
}; 

struct struct_b { 
    struct struct_a; 
    int bb; 
}; 

int main(void) 
{ 
    volatile struct struct_b my_b; 
    my_b.aa = 5; /* not a member of my_b */ 
    my_b.bb = 6; 

} 

結果:

$ gcc -std=c11 struct_extend.c 
struct_extend.c:11:20: warning: declaration does not declare anything 
    struct struct_a; 
        ^
struct_extend.c: In function ‘main’: 
struct_extend.c:18:9: error: ‘volatile struct struct_b’ has no member named ‘aa’ 
    my_b.aa = 5; /* not a member of my_b */ 

相關:

$ gcc --version 
gcc (Debian 6.3.0-18) 6.3.0 20170516 

這難道不是在我的編譯器實現的,還是我做錯了?

+1

的可能的複製[什麼是匿名結構和聯合的有用的C11?](https://stackoverflow.com/questions/8932707/what-are-anonymous-structs-and-unions-useful-for -in-c11) –

+0

在'struct struct_b'聲明中'struct struct_a;'之後需要一些東西。 –

+0

[也與此相關](https://stackoverflow.com/a/44524573/2371524)..底線:爲了確保您的代碼毫無疑問符合您的要求,您必須使用非常詳細的表單,不幸的是。 –

回答

4

標準只允許結構和聯合無標籤作爲無名成員:

6.7.2.1 Structure and union specifiers - Paragraph 13

一個未命名的構件其類型說明符是一個結構說明符 沒有標籤被稱爲匿名結構;一個未命名的成員,其 說明符是一個沒有標籤的聯合說明符,稱爲匿名 聯合。匿名結構或聯盟的成員被認爲是 成爲包含結構或聯盟的成員。如果包含結構或聯合也是匿名的,則這將遞歸地應用 。

你很明顯有一個標籤,所以它是無效的C.你連接的答案並沒有更好的。做一個符合標準的方式的方式,可悲的是非常詳細:

struct struct_b { 
    union { 
     struct struct_a _aa; 
     struct { int aa; }; 
    }; 
    int bb; 
}; 

這真的是沒有什麼被留下深刻印象。人們可以使用宏來避免重複成員聲明,​​但現在它是一種代碼異味。

+0

如果有任何事情嘗試使用'_aa'的地址,那麼該版本的代碼將在別名規則的「現代」解釋下失敗並使用結果指針訪問結構。 – supercat

1

似乎要嘗試使含有int aa匿名無名結構在struct_b,類似於以下:

#include <stdio.h> 

struct struct_b { 
    struct { 
     int aa; 
    }; 
    int bb; 
}; 

int main(void) 
{ 
    volatile struct struct_b my_b; 
    my_b.aa = 5; /* now a member of my_b */ 
    my_b.bb = 6; 

    printf ("my_b.aa: %d\nmy_b.bb: %d\n", my_b.aa, my_b.bb); 

    return 0; 
} 

實施例使用/輸出

$ ./bin/strc2 
my_b.aa: 5 
my_b.bb: 6 

這從直接跟隨標準章節由StoryTeller引用。

+0

我明白了。如果需要在那裏顯式定義內部結構的成員,那麼分組的意義是什麼? – Gauthier

+0

這就是100美元的問題。我已經玩了一下,添加了多個層次和多種類型,並且我沒有看到在結構中嵌入匿名匿名結構的好處。似乎我只是在原始結構本身中聲明變量更有意義。我必須看到標準委員會的會議記錄,但是我懷疑這是爲了「位域」目的在「union」中提供匿名的未命名'struct',事實上你可以使用結構只是工會和結構以相同方式處理的副作用。 –

+0

@ DavidC.Rankin:標準是恕我直言,在那裏非常可怕,尤其是考慮到「現代」別名規則,它假定出現在聯合中的未標記結構不會使用相同成員來標記標記結構。 – supercat

3

根據GCC參考:使用-fms-extensions標誌,這將啓用此功能。

  • 除非使用-fms-extensions,無名字段必須是結構或聯合定義沒有標記(例如,「結構{ INT一個;};」)。如果使用-fms-extensions,則字段還可以是具有諸如‘struct foo { int a; };’之類的標籤的定義的 定義,參考 定義爲先前定義的結構或聯合(諸如「struct foo;」)或對先前定義的typedef名稱的引用結構或 聯合類型。

  • 選項-fplan9-extensions啓用-fms-extensions以及另外兩個擴展。首先,指向結構的指針 自動轉換爲指向匿名字段的指針,用於 賦值和函數調用。

我用下面的命令GCC,它的正常工作。

gcc -std=c11 -O2 -Wall -fms-extensions -pedantic -pthread ls.c