Анонимное объединение в структуре не в c99?

вот очень упрощенный код проблемы, которую я имею:

enum node_type {
    t_int, t_double
};

struct int_node {
    int value;
};

struct double_node {
    double value;
};

struct node {
    enum node_type type;
    union {
        struct int_node int_n;
        struct double_node double_n;
    };
};

int main(void) {
    struct int_node i;
    i.value = 10;
    struct node n;
    n.type = t_int;
    n.int_n = i;
    return 0;
}

И что я не, undestand - это:

$ cc us.c 
$ cc -std=c99 us.c 
us.c:18:4: warning: declaration does not declare anything
us.c: In function ‘main’:
us.c:26:4: error: ‘struct node’ has no member named ‘int_n’

Используя GCC без -std код компиляций опции выше без любых проблем (и подобный код работает вполне прилично), но это кажется этим c99 не разрешает эту технику. То, почему это так, и действительно ли возможно сделать, c99 (или c89, c90) совместимый?Спасибо.

49
задан timrau 18 August 2012 в 13:55
поделиться

4 ответа

Анонимные объединения - это расширение GNU, а не часть какой-либо стандартной версии языка C. Вы можете использовать -std = gnu99 или что-то подобное для расширений c99 + GNU, но лучше написать правильный C и не полагаться на расширения, которые не предоставляют ничего, кроме синтаксического сахара ...

Изменить: Были добавлены анонимные союзы в C11, поэтому теперь они являются стандартной частью языка. Предположительно -std = c11 GCC позволяет вам их использовать.

62
ответ дан 7 November 2019 в 11:38
поделиться

Ну, решением было назвать экземпляр объединения (который может оставаться анонимным как datatype) и затем использовать это имя в качестве прокси.

$ diff -u old_us.c us.c 
--- old_us.c    2010-07-12 13:49:25.000000000 +0200
+++ us.c        2010-07-12 13:49:02.000000000 +0200
@@ -15,7 +15,7 @@
   union {
     struct int_node int_n;
     struct double_node double_n;
-  };
+  } data;
 };

 int main(void) {
@@ -23,6 +23,6 @@
   i.value = 10;
   struct node n;
   n.type = t_int;
-  n.int_n = i;
+  n.data.int_n = i;
   return 0;
 }

Теперь он компилируется как c99 без каких-либо проблем.

$ cc -std=c99 us.c 
$ 

Примечание: я все равно не в восторге от этого решения.

5
ответ дан 7 November 2019 в 11:38
поделиться

Union должен иметь имя и быть объявлен следующим образом:

union UPair {
    struct int_node int_n;
    struct double_node double_n;
};

UPair X;
X.int_n.value = 12;
1
ответ дан 7 November 2019 в 11:38
поделиться

Глядя на 6.2.7.1 C99, я вижу, что идентификатор необязателен:

struct-or-union-specifier:
    struct-or-union identifier-opt { struct-declaration-list }
    struct-or-union identifier

struct-or-union:
    struct
    union

struct-declaration-list:
    struct-declaration
    struct-declaration-list struct-declaration

struct-declaration:
    specifier-qualifier-list struct-declarator-list ;

specifier-qualifier-list:
    type-specifier specifier-qualifier-list-opt
    type-qualifier specifier-qualifier-list-opt

Я облазил весь поиск вдоль и поперек, и не могу найти никаких ссылок на то, что анонимные союзы противоречат спецификации. Весь суффикс -opt указывает на то, что вещь, в данном случае идентификатор, является необязательной согласно 6.1.

1
ответ дан 7 November 2019 в 11:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: