2010-03-03 5 views
2

Этого кода имеет интересную ошибку:Порядка оценки назначения (я нашел свою первую ошибку компилятора?)

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; 
} 

Теперь я полностью покинуть здесь, или же виновный компилятор «ХСС» просто отображает ошибку?

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

+4

Это не ошибка компилятора, это ошибка программиста: код включает неопределенное поведение и поэтому недействителен. C – Christoph

+0

http://catb.org/~esr/faqs/smart-questions.html#id382249 –

+0

Я предлагаю вам google up undefined поведение. –

ответ

8

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

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

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

+0

Ах, конечно. Это не объясняет, почему работает второй пример, но поскольку это неопределенное поведение, я предполагаю, что оно не обязательно должно быть последовательным :-) – Christoffer

+0

Второй пример - это ОК, потому что 'i' не изменен - ​​он просто читается дважды (приращение происходит в отдельном выражении, после точки последовательности). Два объекта, которые * * изменены, различны (так что это тоже ОК). – caf

+0

Да, я на самом деле немного смущен, что я не видел его для себя, я полагаю, мне нужен еще один набор глаз, чтобы определить проблему.(В свою защиту я хотел бы добавить, что предлагаемый патч, который я рассматривал, составлял ~ 500 строк кода, это была только одна из проблем :-) – Christoffer

5

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

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

+0

Это правда. +1 от меня. –

0

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

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