Похоже, вы подлежат неустановленный поведение здесь, так как порядок вычисления выражений списка инициализации не задан, из проекта C99 стандартной секции 6.7.8
:
Порядок, в котором какие-либо побочные эффекты встречаются среди списка выражений инициализации не определен , 133)
и отметить 133 говорит:
В частности, порядок оценки не должны быть такими же, как и порядок инициализации подобъектов.
Насколько я могу судить, нормативное текст, который поддерживает записку 133
бы из раздела 6.5
:
За исключением указанных позже [...] порядок оценки подвыражений и порядок, в котором происходят побочные эффекты, равны как неуказанным.
и мы можем видеть, что intializer является полным выражением из 6.8
(курсив):
Полное выражение является выражением, которое не является частью другого выражения или декларатора. Каждое из следующих вариантов является полным выражением: инициализатор; [...]
Посмотрев назад на одном из моих old C++ answers, который покрывал точки последовательности в инициализаторе и который помещает полного выражение в другом месте, то я первоначально пришел к выводу, я понял, что грамматика в 6.7.8
содержала инициализатору дважды:
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designationopt initializer
initializer-list , designationopt initializer
первоначально я не заметил этого и мысли заявление на полные выражения применяется к верхнему элементу в указанной выше грамматике.
Сейчас я считаю, как C++ полного выражение относится к каждому инициализатору в инициализаторе-листе, которые делают мой предыдущий анализ неверен.
Defect report 439 подтвердил мое подозрение, что это было действительно так, то он содержит следующий пример:
#include <stdio.h>
#define ONE_INIT '0' + i++ % 3
#define INITIALIZERS [2] = ONE_INIT, [1] = ONE_INIT, [0] = ONE_INIT
int main()
{
int i = 0;
char x[4] = { INITIALIZERS }; // case 1
puts(x);
puts((char [4]){ INITIALIZERS }); // case 2
puts((char [4]){ INITIALIZERS } + i % 2); // case 3
}
и говорит:
В каждом использовании макроса Инициализаторы, переменная я есть увеличился три раза. В случаях 1 и 2 нет неопределенного поведения, потому что приращения находятся в выражениях, которые неопределенно секвенированы по отношению друг к другу, а не нелогичны.
поэтому каждый intializer в INITIALIZERS
является полного выражения.
Поскольку этот отчет дефекта против C11, стоит отметить, что C11 более многословный, то C99 в нормативном тексте по этому вопросу, и он говорит:
Оценка выражений списка инициализации неопределенно секвенировала по отношению друг к другу и, следовательно, к порядку , в котором происходят какие-либо побочные эффекты, не указывается. 152)
Существует неопределенное поведение в случае, когда следующие выражения вычисляются до соответствующих элементов в values
назначены:
values[0] + values[5]
или:
values[5]/10
Эта это неопределенное поведение, поскольку используется indeterminate value invokes undefined behavior.
В данном конкретном случае простейших обходный будет выполнять расчеты вручную:
int values[10] = {
[0]=197,[2]=-100,[5]=350,
[3]= 197 + 350,
[9]= 350/10
};
Есть и другие варианты, такие как делать задание к элементу 3
и 9
после инициализации.
W-что это за синтаксис синтаксиса сумасшедшего? Как же это законно и компилируется? – tux3
@ tux3: https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html – Mat
Это специфичный компилятор gcc: http://stackoverflow.com/questions/201101/how -to-initialize-a-array-in-c второй тент. – hetepeperfan