Порядок оценки заданий (нашел ли я свою первую ошибку компилятора?) - PullRequest
2 голосов
/ 03 марта 2010

В этом коде есть интересная ошибка:

some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     struct_array1[i].value = struct_array2[i++].value = 1)
    ;

Для большинства компиляторов приведенный выше код приводит к установке поля «значение» всех структур в соответствующих массивах в 1. Однако для одного конкретного компилятора (назовем его xcc) структуры в struct_array1 НЕ инициализируются правильно. Поле "значение" установлено в 0 для всех структур, что меня как-то удивило.

Следующий фрагмент кода работает должным образом на всех компиляторах:

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     i++)
{
    struct_array1[i].value = struct_array2[i].value = 1;
}

Теперь я полностью отключен, или компилятор-нарушитель "xcc" просто отображает ошибку?

Я не могу найти ничего, что отображало бы специфичное для реализации поведение в первом фрагменте кода; из того, что я понимаю, приращение постфикса должно иметь приоритет над назначениями, а назначения должны оцениваться справа налево. С первым фрагментом кода не должно быть ничего странного, кроме того, что он немного нечитабелен.

Ответы [ 3 ]

8 голосов
/ 03 марта 2010

Вы вызвали неопределенное поведение, потому что оно изменяет i, а также извлекает его значение для другой цели, кроме вычисления нового значения, без промежуточной точки последовательности.

Соответствующей частью стандарта C99 является этот раздел в разделе 6.5:

Между предыдущей и следующей последовательностью указать объект должен храниться значение, измененное не более одного раза оценка выражения. Кроме того, предыдущее значение должно быть только чтение, чтобы определить значение, которое будет сохраняется.

5 голосов
/ 03 марта 2010

struct_array1[i].value = struct_array2[i++].value = 1

Я думаю, что это неопределенное поведение, потому что i++ не гарантирует завершение всех его побочных эффектов, пока не будет достигнута следующая точка последовательности. Следующая точка последовательности - это «мнимая» ; в конце оператора. Это распространенная ошибка, я думаю, что вы можете найти много тем на SO, относящихся к ней, просто ищите точки последовательности.

0 голосов
/ 03 марта 2010

На самом деле мы не должны выполнять более одной оценки для одной и той же переменной, в признаке

выражение. Если мы сделаем это, это будет неопределенное поведение.

...