2016-07-27 4 views
-2

ISO/IEC 9899 (СК2) §6.5 - 2 Выражения говорит нам:Почему printf ("% d% d% d", ++ i, i, i ++) - неопределенное поведение?

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

Это то, что я имел в виду, помнил и сказал бы, что кто-нибудь спросит меня, почему строка из названия дает неожиданные результаты.

Но сегодня я только что обнаружил эту линию:

§7.19.6 - 1 отформатированные функции ввода/вывода:

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

Что заставило меня предположить:

Хотя

int i = 0; 
printf ("%d, %d", ++i, i++); 

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

int i = 0; 
printf ("%d, %d, %d", ++i, i, i++); 

Но выход есть:

2, 2, 0 

Я никогда не видел лучшего примера, указывающего на неопределенное поведение.

Но почему? Если условие истинно

«[...] ведут себя так, как будто существует точка последовательности после действий, связанных с каждым спецификатором.»

затем применяя правило под §6.5 - 2 на каждый из actiosn, связанный с спецификатором не позволяет пересекать это правило, как в:

(ИП, представляющие собой соответствующую точку последовательности)

ИП ++i ИП i ИП i++

Начиная с SP1 в заданном диапазоне между предыдущим и следующим SP, ++i является единственной модификацией сохраненного значения i.

От SP2 что находится в диапазоне между предыдущим и следующим SP: ++i и i где ++i все еще является единственной модификацией этого значения.

Если мы теперь возьмем SP3 все, что происходит между предыдущим SP (SP2) и следующий SP (конец вызова) является:

i и i++ еще только одна модификация i в целом диапазон между предыдущим и следующим SP.

Так что же я интерпретирую здесь неправильно о том, как работают точки последовательности?

+0

Не стесняйтесь, если считаете, что это приемлемо. Но обратите внимание, что это не просто еще один вопрос о доме. Я столкнулся с чем-то, что мне показалось странным, и я немного успокоился, и я ясно дал понять, что это путаница и почему он отличается от других вопросов об этом. Если вы все еще думаете, что я что-то пропустил или не приложил усилий, пожалуйста, дайте мне знать, почему вы так думаете. – dhein

ответ

1

Проблема заключается не в действиях, связанных с спецификаторами. Проблема заключается в вычислении параметров функции printf, которая завершена до того, как первый спецификатор выполнит любые действия.

Представьте себе, если код был:

void foo (int i1, int i2, int i3) 
{ 
    printf("%d, %d, %d", i1, i2, i2); 
} 

foo (++i, i, i++); 

Здесь было бы вполне понятно. И обертка ничего не меняет.

+0

Можете ли вы уточнить, в каких случаях эти точки последовательности между отдельными действиями даже имеют значение, если это так? Или я должен спросить об этом как о отдельном вопросе? – dhein

+0

Это должно быть очевидно для таких вещей, как 'scanf'. Там могут быть некоторые спецификаторы формата, где он может сделать другой для 'printf', но я не могу придумать. Может быть, кто-то другой может. –

+2

В частности, спецификатор формата '% n', который записывает количество символов, напечатанных до сих пор на указанный адрес. –

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