2013-12-21 3 views
1

Может ли кто-нибудь объяснить это поведение?«элемент инициализации не является постоянным» с использованием назначенного инициализатора на статической структуре с C99

Используя флаг компилятора std=c99 я получаю следующие ошибки:

  • «инициализатор элемент не является постоянная» для b1.
  • Ожидаемое выражение перед '.' токен "для b2
  • b3 в порядке.

Когда не используется -std=c99, все линии в порядке. Если статический b1 не используется, это нормально. Я использую GCC.

typedef struct A_tag { 
    int v; 
    int w; 
} A; 

typedef struct B_tag { 
    A super; 
    int x; 
    int y; 
} B; 

void test(){ 
static B b1 = ((B){.super={.v=100}, .x=10}); 
static B b2 = ({.super={.v=100}, .x=10}); 
static B b3 = {.super={.v=100}, .x=10}; 
} 
+0

Почему '(B)' перед инициализацией? – haccks

+0

@JoachimPileborg Ваше утверждение неверно, оно связано с C99. Ошибка возникает также с '-std = gnu99', но исчезает с' -std = c89' или '-std = gnu89'. Неожиданно clang принимает код с флагом C99 и без него. – usr1234567

+0

Я просто добавил еще одну ошибку при установке инициализатора в скобки. Мне нужны эти скобки, потому что я хочу использовать инициализатор в макросе. обходной путь: #define PROTECT (...) __VA_ARGS__ – Dill

ответ

7

(B){.super={.v=100}, .x=10} не является «слепок», но в целом это «соединение буквальным» временный объект, который живет только внутри соответствующего выражения (в основном). Поскольку это не постоянный, а временный объект, по стандарту вы не можете его инициализировать.

+0

nice: int vv = ((B) {. Super = {. V = 100}, .x = 10}) .v; – Dill

0

Как указано выше, это «сложный литерал». Может ли он использоваться для инициализации, это фактически реализация, определенная IMO. В стандарте C11 говорится в [6.7.9 §4], что «выражения в инициализаторе для объекта, который имеет статическую или длительность хранения потоков, должны быть постоянными выражениями или строковыми литералами». Затем в [6.6 §7] перечислены, какие константные выражения могут быть, и [6.6 §10] он позволяет реализации «принимать другие формы постоянных выражений».

Поскольку «составные литералы» по определению являются постоянными, его можно использовать для инициализации, хотя стандарт явно не говорит об этом. (И многие компиляторы действительно принимают его.)

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