2014-02-19 4 views
1

Зачем мне нужны вложенные фигурные скобки для компиляции этого кода?Вложенные фигурные скобки и назначенные инициализаторы

#include <stdio.h> 
#include <stdlib.h> 

typedef union TEST TEST; 

union TEST { 
    int type; 
    char *things; 
}; 


int main() { 

    TEST test[] = {1, 2, .things = NULL}; // Compile time error 

    TEST test[] = {1, 2, {.things = NULL}}; // Works, but I didn't check at run time 

    return 0; 
} 

Почему первое задание не работает?
Зачем нужны внутренние брекеты?
Есть ли способ работать в первом задании? Без внутренних брекетов?

Спасибо!

+0

Возможный дубликат: [инициализировать массив объединения при объявлении] (http://stackoverflow.com/questions/11558390/initialize-a-union-array-at-declaration). См. Первый [ответ] (http://stackoverflow.com/a/11558466/519383). –

+0

Не думаю, что я использую C99 уже, мне интересно, зачем нужны внутренние фигурные скобки ... – drigoSkalWalker

+0

В этом вопросе нет сложных литералов. –

ответ

1

В итоге: {1, 2, .things = NULL} попытки инициализировать элемент массива test, который называется things, но массив не имеет элемент с именем things, так что это является недопустимым. Напротив, {1, 2, {.things = NULL}} пытается инициализировать элемент второго элемента массива с именем things, а второй элемент массива - это объединение, которое имеет член с именем things, поэтому это действительно.

Per C 2011 (N1570) 6.7.9 17:

Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union. In contrast, a designation causes the following initializer to begin initialization of the subobject described by the designator. Initialization then continues forward in order, beginning with the next subobject after that described by the designator.

Существует еще в последующих пунктах о том, как текущий объект обрабатывается, но это достаточно. В списке инициализаторов, заключенном в скобки, 1 - простой инициализатор; у него нет никаких обозначений. Таким образом, он инициализирует подобъект массива, который является элементом массива. Аналогично 2 инициализирует другой элемент. Затем мы имеем .things = NULL. У этого есть указатель, .things.

В соответствии с цитируемым абзацем этот указатель .things вызывает инициализацию подобъекта, описанного .things. Но в массиве нет ничего, что обозначено .things. Это только массив с индексированными элементами, обозначенный [index]. У него нет членов, назначенных .thigns. Таким образом, есть ошибка.

Во втором списке, где используются дополнительные распорки, пункт 20 применяется:

If the aggregate or union contains elements or members that are aggregates or unions, these rules apply recursively to the subaggregates or contained unions. If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the elements or members of the subaggregate or the contained union.…

В этом случае {.things = NULL} начинается с левой фигурной скобкой. Это говорит о том, что инициализаторы, содержащиеся в фигурных скобках, инициализируют текущий объект большего списка. Поэтому они инициализируют следующий элемент массива (элемент с индексом 2). Любой элемент массива представляет собой объединение с членом с именем things, поэтому .things обозначает в нем подобъект, и этот синтаксис является приемлемым.

+0

Да, я думаю, что получил: я использовал назначенный инициализатор не так, я пытался получить доступ к члену профсоюза, но компилятор ждал индекса массива test, а не члена .things объединения ... Сказал, что ... Вы хоть представляете, как выполнить первую попытку назначения без внутренних брекетов? – drigoSkalWalker

+0

Странная часть - ошибка компиляции gcc: teste.c: 14: 5: error: имя поля не в записи или инициализатор объединения С записью он хочет иметь массив значений? Я не знаю, английский не мой язык. – drigoSkalWalker

+0

TEST * test = (TEST []) {1, 2, [3] .things = NULL}; // Теперь это работает! Вы знаете какой-либо способ достичь этого, не застревая в позиции индекса, вы знаете часть '[3]' ... извините мой плохой английский, я думаю, вы поняли. – drigoSkalWalker

3

Тот факт, что вам не нужны внутренние фигурные скобки для первых двух элементов, является нечетной деталью в синтаксисе списков инициализаторов, что позволяет инициализировать объединение в качестве первого элемента. Я бы предложил использовать фигурные скобки и обозначение для все инициализаторы в списке, а не только .things.

+0

Для меня не имеет смысла использовать внутренние фигурные скобки ... Я все еще сомневаюсь – drigoSkalWalker

+1

Рассмотрите: что, если 'TEST' были структурой вместо объединения? Правила почти одинаковы между этими двумя. Вы инициализировали бы структуру, содержащую 'int' и' char * ', установив ее на' 3'? – Sneftel

+0

У меня есть ваша точка зрения, она имеет смысл со структурой, но я не чувствую то же самое с union. – drigoSkalWalker

Смежные вопросы