Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222

Побочные эффекты a = (b = c)

29.07.2013, 20:03. Показов 1735. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В связи с этой темой хотелось бы уточнить:
C
1
a = (b = c)
гарантируется ли, что запись в b будет раньше, чем запись в a?
ИМХО, в C99 - нет (6.5.16.3: "The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point"). Насчёт C11 не уверен, но вроде тоже нет (в отличие от C++11, где в 5.17.1 явно написано, что "assignment is sequenced... before the value comutation of the assignment expression").
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.07.2013, 20:03
Ответы с готовыми решениями:

Побочные эффекты в си
По какому принципу выполняются выражения типа: u += (a = 1) + (a = 2); u += ((a = 1) || (a = 2)); (для int a, u)

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

Побочные эффекты после изменения innerHTML
Пишу .user.js, и столкнулся со следующей проблемой: Есть набор дивов одного класса. Есть .js отдельным файлом, в котором реализовано...

18
1 / 1 / 1
Регистрация: 15.06.2013
Сообщений: 83
29.07.2013, 22:03
Скобки имеют приоритет выше, чем присваивание, значит, б присваивается с и присваивается а
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
30.07.2013, 01:50
Да оно и без скобок гарантируется - оператор = выполняется справа налево, то есть сначала будет вычеслено b = c, и только за тем a = b. Перечитайте главу "Приоритет и очерёдность вычислений" в КиР, там подробно описаны ситуации, когда очерёдность вычислений не определена. Это не тот случай.
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
30.07.2013, 11:25  [ТС]
Цитата Сообщение от easybudda Посмотреть сообщение
то есть сначала будет вычеслено b = c, и только за тем a = b
Вычислено - это да. То есть результатом b = c будет то, что было в c, и это будет rvalue. Дальше будет вычислен результат a = (b = c). Но запись в a и в b - это побочный эффект, который может произойти в любой время между точками следования (C99).
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand. The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
02.08.2013, 10:36
Цитата Сообщение от Somebody Посмотреть сообщение
гарантируется ли, что запись в b будет раньше, чем запись в a?
сначала вычисляются операнды первого присваивания
правый операнд является присваиванием, поэтому при его вычислении вычисляются его операнды
после вычисления операндов второго присваивания оно выполняется и операция возвращает новое содержимое левого операнда
после этого правый операнд вычислен и выполняется первое присваивание

Цитата Сообщение от easybudda Посмотреть сообщение
Перечитайте главу "Приоритет и очерёдность вычислений" в КиР
не перечитать надо, а просто прочитать книгу, потому что там куча примеров с таким присваиванием без всяких скобок

Цитата Сообщение от Somebody Посмотреть сообщение
ИМХО, в C99 - нет (6.5.16.3
такого пункта там нет, есть 6.5.16 и в нём третий блок

я так понял, что побочные эффекты, получающиеся при записи в левое значение, гарантированно происходят уже после того как операнды вычислены (это уточнено в C11)

Цитата Сообщение от Somebody Посмотреть сообщение
Хм... Вообще, мне кажется, что даже
C
1
2
int d = 10;
printf("%d %d", d = 10, d = 10);
это уже undefined behaviour.
порядок вычисления аргументов функции не определён, но гарантируется, что каждый аргумент будет вычислен в значение и оно будет передано
так что никакого undefined behavior
1
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 13:27  [ТС]
Для начала: я не говорю, что здесь операдны могут вычисляться не в том порядке. Можно и без скобок, конечно. Вопрос только в порядке записи. А истина всё-таки в стандарте, а не в K&R...
Цитата Сообщение от accept Посмотреть сообщение
после вычисления операндов второго присваивания оно выполняется и операция возвращает новое содержимое левого операнда
Вроде бы, действительно, значение левого операнда после присваивания:
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue.
Но в таком случае предложение:
The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.
кажется избыточным, ну да ладно.
Порядок записи будет важен, если переменные volatile. И тогда получается такой интересный момент:
C
1
2
volatile int a, b;
a = b = 0;
Здесь в a в теории должно записаться то, что прочитается из b, а не 0? Интересно... Вот, нашёл обсуждения на эту тему:
http://stackoverflow.com/quest... b-1-read-b
http://stackoverflow.com/quest... d-volatile
В C11 на этот счёт появилось примечание:
111) The implementation is permitted to read the object to determine the value but is not required to, even when the object has volatile-qualified type.
Далее:
Цитата Сообщение от accept Посмотреть сообщение
порядок вычисления аргументов функции не определён, но гарантируется, что каждый аргумент будет вычислен в значение и оно будет передано
так что никакого undefined behavior
Но там два раза изменение d, это попадает под "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression", даже если одно и то же значение пишется, не?

Теперь к тому, с чего всё началось в предыдущей теме, более конкретно:
C
1
a -= b = (a += b) - b;
C99: независимо от того, что в каком порядке пишется, всё равно будет изменение объекта более одного раза между точками следования - undefined behavior. Так?
C11:
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
Тоже undefined, получается.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
02.08.2013, 14:04
Цитата Сообщение от Somebody Посмотреть сообщение
Теперь к тому, с чего всё началось в предыдущей теме, более конкретно:
C
1
a -= b = (a += b) - b;
C99: независимо от того, что в каком порядке пишется, всё равно будет изменение объекта более одного раза между точками следования - undefined behavior. Так?
Не так. Сначала будет вычеслено a += b за тем b = a - b а за тем a -= b. В результате a и b поменяются значениями. Если ваш компилятор сделает что-то другое - избавьтесь от него.
Другой случай:
C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main(void) {
    int a = 0;
    
    printf("%d %d\n", 1 + a, ++a);
    
    return 0;
}
у меня вывело 2 1, но я бы не стал ставить на то, что так будет на любой системе при любом компиляторе, даже не смотря на http://codepad.org/trPIu370
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 14:11  [ТС]
Цитата Сообщение от easybudda Посмотреть сообщение
Не так. Сначала будет вычеслено a += b за тем b = a - b а за тем a -= b. В результате a и b поменяются значениями. Если ваш компилятор сделает что-то другое - избавьтесь от него.
Как же насчёт того, что нельзя изменять объект больше одного раза между точками следования? По такой логике
C
1
i = ++i + 1;
это тоже нормально? Но это 100% ub, потому что это пример из стандарта.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
02.08.2013, 15:02
Цитата Сообщение от Somebody Посмотреть сообщение
это тоже нормально? Но это 100% ub, потому что это пример из стандарта.
Если можно, раздел укажите, да и сам стандарт, а то Вы их тут уже несколько обозначили... И кстати, откровенно не понимаю, что не так в этом выражении. Сначала текущее значение i увеличивается на единицу, за тем к получившемуся значению прибавляется константа (1 в этом случае) и всё это веселье (результат сложения) присваивается переменной i. А какие ещё есть варианты? По сути тоже самое, что
C
1
i = ( i += 1 ) + 1;
Беда была бы, если бы было
C
1
i = ( i += 1 ) + ( i -= 2 );
т.к. тут результат зависит от того, выражение в каких скобках посчитается первым.
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 16:01  [ТС]
Дополнение к тому большому посту:
Цитата Сообщение от Somebody Посмотреть сообщение
Вроде бы, действительно, значение левого операнда после присваивания
Кстати, если бы и правда это был единственно возможный вариант, то было бы странно, что i = ++i + 1 приведено в примере как undefined, потому что оно чисто формально не соответствует пунтку про модификацию между точками следования без какого-либо дополнительного здравого обоснования. Так что, имхо, это следует читать так же, как и в C11.

Цитата Сообщение от easybudda Посмотреть сообщение
Если можно, раздел укажите, да и сам стандарт, а то Вы их тут уже несколько обозначили
C99, C11.
http://www.open-std.org/jtc1/s... /n1256.pdf
https://github.com/maeikei/por... /n1570.pdf
Примечание в начале раздела 6.5 и в том, и в другом.
Допустим, C99: не так как минимум то, что это формально не соответствует фразе "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.72) Furthermore, the prior value shall be read only to determine the value to be stored.73)".
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
02.08.2013, 16:07
Цитата Сообщение от Somebody Посмотреть сообщение
Примечание в начале раздела 6.5
Точно, увидел. Странно как-то... Но спорить глупо - стандарт всё-таки...
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
02.08.2013, 16:14
Цитата Сообщение от Somebody Посмотреть сообщение
А истина всё-таки в стандарте, а не в K&R...
К&R2 написана по стандарту

Цитата Сообщение от Somebody Посмотреть сообщение
Здесь в a в теории должно записаться то, что прочитается из b, а не 0?
всё то же самое будет
volatile означает, что значение может меняться
Цитата Сообщение от Somebody Посмотреть сообщение
111) The implementation is permitted to read the object to determine the value but is not required to
в любом случае у операции есть возвращаемое значение, которое и будет использоваться дальше

Цитата Сообщение от Somebody Посмотреть сообщение
Но там два раза изменение d, это попадает под "Between the previous and next sequence point
previous and next sequence point - это всё внутри одной операции присваивания

Цитата Сообщение от Somebody Посмотреть сообщение
C
1
a -= b = (a += b) - b;
и всё в кучу мешать нельзя, простое и составное по-разному работают
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 17:03  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
К&R2 написана по стандарту
Не по C99 или C11...
Цитата Сообщение от accept Посмотреть сообщение
всё то же самое будет
volatile означает, что значение может меняться
C
1
a = b = 0;
В b записывается 0. Что должно записаться в a? Ноль как результат присваивания или b как значение левого операнда после присваивания? В случае с volatile это же не обязательно будет 0. Может быть, результат чтения из b вообще даже никогда не бывает нулём...
Цитата Сообщение от accept Посмотреть сообщение
в любом случае у операции есть возвращаемое значение, которое и будет использоваться дальше
Есть, но откуда это за значение берётся? В примечании в C11 не зря же оговаривается "even when the object has volatile-qualified type" - потому что при написании такого кода может быть важно это знать.
Цитата Сообщение от accept Посмотреть сообщение
previous and next sequence point - это всё внутри одной операции присваивания
The following are the sequence points described in 5.1.2.3:
— The call to a function, after the arguments have been evaluated (6.5.2.2).
— The end of a full declarator: declarators (6.7.5);
— Immediately before a library function returns (7.1.4).
— After the actions associated with each formatted input/output function conversion
specifier (7.19.6, 7.24.2).
— Immediately before and immediately after each call to a comparison function, and
also between any call to a comparison function and any movement of the objects
passed as arguments to that call (7.20.5).
Где sequence point'ы? Перед присваиваниями - это после объявления переменных. После присваиваний - это перед вызовом функции. Между ними - не вижу где...
Цитата Сообщение от accept Посмотреть сообщение
и всё в кучу мешать нельзя, простое и составное по-разному работают
Ладно, если взять
C
1
a = b = a;
то сказанное применимо и к этому случаю, тут изменяется a и при этом она же в другом месте читается.
0
 Аватар для lowercase
213 / 202 / 85
Регистрация: 09.05.2012
Сообщений: 494
02.08.2013, 18:44
не углубляясь в раскаленную атмосферу страстей...
никогда не понимал этих срачей и холиваров а-ля i = i++ + ++i; зачем все усложнять и делать код чертвоски запутанным, неоднозначным и непонятным? KISS же. не уверен в инструкции которую написал? - прочти документацию! не помогло? - сделай проще! не можеш проще? - ты _________________ а не программист(вписаить прилагательное в зависимости от ваших морально-этических взглядов и принципов).
C
1
2
int x, y, z;
x = y = z = 0;
не уверен в этом? документация непомогла?
сделай, то в чем ты уверен.
C
1
int x = 0, y = 0, z = 0;
тоже не уверен? сделай еще проще!
C
1
2
3
int x = 0;
int y = 0;
int z = 0;
...в конечном счете все сведется к асемблерному mov, коих в любом случае будет 3 штуки (если я не ошибаюсь).
языки же предоставляют несколько путей для решения задач(имею ввиду на уровне инструкций), то есть одну и ту же задачу можно решить несколькими способами(как было продемонстрировано выше). зачем усложнять?
1
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 18:58  [ТС]
Цитата Сообщение от lowercase Посмотреть сообщение
C
1
2
int x, y, z;
x = y = z = 0;
Нет проблем, более чем уверен. Теперь возьмём
C
1
2
3
volatile int x, y, z;
...
x = y = z = 0;
На что это заменить? Вариант 1:
C
1
2
3
volatile int x, y, z;
...
z = 0; y = 0; x = 0;
Вариант 2:
C
1
2
3
volatile int x, y, z;
...
z = 0; y = z; x = y;
А ведь это совсем разные вещи, если x, y, z - например, порты ввода/вывода.
0
 Аватар для lowercase
213 / 202 / 85
Регистрация: 09.05.2012
Сообщений: 494
02.08.2013, 19:24
все зависит от результата который вы хотите получить.
1
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 19:32  [ТС]
Цитата Сообщение от lowercase Посмотреть сообщение
все зависит от результата который вы хотите получить.
А, понял мысль. Может быть, это и плохо так возиться с теорией, но она меня всё равно интересует...
0
 Аватар для lowercase
213 / 202 / 85
Регистрация: 09.05.2012
Сообщений: 494
02.08.2013, 19:40
Цитата Сообщение от Somebody Посмотреть сообщение
А, понял мысль. Может быть, это и плохо так возиться с теорией, но она меня всё равно интересует...
первый ответ был на вопрос по поводу a = (b = c). Я разделяю ваш сарказм(?), и скажу в данном случае моей компетентности может не хватить.
я имел ввиду, что если вам нужно занулить занения переменных. но вы не уверенны x = y = z = 0; то ведь это можно сделать простым и более очевидным способом
C
1
int x = 0, y = 0, z = 0;
даже в сулчае с volatile(?)
то есть тут вы получите то, что ожидаете.
на этом моя компетенция закачивается и как быть в инном случае я уже, к сожалению, сказать немогу. могу лишь делать некоторые предположения, которые, не факт, что будут верными.
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.08.2013, 19:52  [ТС]
Я про то, что понятно, что если нужно написать код, который что-то делает, то можно написать так, что ни у кого не будет вопросов, как он работает. Проблемы начинаются, когда, код уже есть, а что он должен делать - неясно. Например, при написании компилятора.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.08.2013, 19:52
Помогаю со студенческими работами здесь

Проблемы при вызове метода: это выражение вызывает побочные эффекты
В таком коде: double Zlin = { { 8, 3, 3.22, 10.88 }, { 3, 2, 4.98, 8.54 }, { 1, 2, 7.31, 12.54 }, { 7, 1, 5.06, 12.9 }, { 7, 5, 3.34,...

Что означает сообщение компилятора: элемент вызывает побочные эффекты и не будет вычислен
Здравствуйте. Помогите разобраться. Есть программа по учёту номеров телефонов. В ней есть свойство private Dictionary&lt;string,...

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

Главные и побочные диагонали матрицы
Всем доброго времени суток:) Очень интересует вопрос операций над главными и побочными диагоналями, пока что я плохо в этом разбираюсь....

двумерный массив- побочные диагонали
Привет всем. Пишу на Си. Как в матрице(двумерный массив mass) найти минимальный элемент, лежащий ниже побочной диагонали? и как вообще...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru