Порядок вычисления: подвыражения, точки последовательности и приращения постфикса в C - PullRequest
0 голосов
/ 30 мая 2018

Дискуссия возникла вокруг оператора C x = b[i] + i++; и его определенности.

Аргумент в пользу того, что указанное утверждение не определено, выглядит примерно так:

§ 6.5 состояний C99:

[…] порядок вычисления подвыражений и порядок возникновения побочных эффектов не определены.

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

Однако я по-разному интерпретирую указанную спецификацию.

§ 6.5 C99 дополнительно заявляет:

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

§ 5.1.2.3 C99-состояний:

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

Список точек последовательности приведен в приложении C, и только следующие совпадениярассматриваемое утверждение ИМХО.

Конец полного выражения

Оценка b[i] (значение элемента i из b) изначение i++ (просто i) может произойти в любом порядке до добавления (и оценки =, которая является значением RHS).Однако побочные эффекты всего оператора откладываются до окончания всех этих оценок, поскольку это единственная точка последовательности.В этом случае побочными эффектами являются изменение x и увеличение i.

Кто прав?Есть ли дополнительные параграфы, имеющие отношение к аргументу?Чем отличается в C ++?

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

§6.5.2.4 состояния

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

Так же, какЮджин комментарий предложил.В случае, если это не достаточно ясно, утверждение, приведенное в вопросе в § 6.5 (1)

, предшествующее значение должно быть прочитано только для определения значения, которое будет сохранено.

нарушается также напрямую.Значение i не только считывается, чтобы определить значение после приращения, но и является операндом оператора индекса.

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

0 голосов
/ 30 мая 2018

Ваша цитата из раздела 6.5 является релевантной:

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

(уточнение мое.)

В вашем утверждении значение i изменяется и используется как индекс для b.Ваше утверждение не содержит внутренних точек последовательности, поэтому эти эффекты должны возникать между одной и той же парой точек последовательности.Заявление поэтому нарушает указанное требование.Затем применяется параграф 2 раздела 4:

Если требование «должен» или «не должен» нарушается, то поведение не определено.[...]

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

Тем не менее, вы утверждаете, что

побочные эффекты всего оператора откладываются до окончания всех этих оценок, потому что это единственная последовательностьточка.

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

0 голосов
/ 30 мая 2018

Побочные эффекты не должны откладываться до точки последовательности - они могут применяться сразу после оценки.Или нет.

C 2011 имеет немного другой (более точный) язык:

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

C 2011, §6.5 ¶2

i++ имеет побочный эффект на i, b[i] использует i при вычислении значения, и два подвыражения не секвенированы относительно друг друга (т.е.нет промежуточной точки последовательности).Таким образом, поведение b[i] + i++ не определено.

...