Я изучал в лекциях, что постфиксные и префиксные операторы увеличивают значение только после получения точки с запятой.
Пришлите ко мне своего лектора, чтобы я отнесла ему бейсбольную биту вежливо указала на его ошибку.
Когда применяется побочный эффект пре- или постфикса ++
и --
, он не указан, за исключением требования, чтобы это произошло до следующей точки последовательности. В выражении вроде
x = a++ * b
a
может быть обновлено сразу после того, как a++
будет оценено, или обновление может быть отложено до тех пор, пока a++ * b
не будет оценено и результат не будет присвоен x
, или где-то между ними.
Вот почему такие выражения, как i++ * i++
, printf("%d %d", c++, c)
и a[i++] = i
, а также множество других, являются плохим juju. Вы получите разные результаты в зависимости от компилятора, настроек оптимизации, окружающего кода и т. д. Стандарт языка явно оставляет поведение неопределенным, так что компилятор не обязан "делать правильные вещи", что бы то ни было. может быть и правильно. Помните, что определение неопределенного поведения таково:
3.4.3
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
Это преднамеренное дизайнерское решение — причина того, что порядок этих операций не указан, состоит в том, чтобы дать реализации возможность изменять порядок вычислений в целях оптимизации. Однако в обмен на эту свободу некоторые операции не будут иметь четко определенных результатов.
Обратите внимание, что компилятор может попытаться обнаружить эти случаи и выдать диагностику; printf("%d %d", c++, c);
было бы достаточно легко поймать, но в общем случае это было бы ошибкой для обнаружения. Представьте, если бы это было написано printf("%d %d", (*p)++, c)
; если p
указывает на c
, то поведение не определено, в противном случае все в порядке. Если p
назначено в другой единице перевода, то во время компиляции невозможно узнать, является ли это проблемой или нет.
Эту концепцию нетрудно понять, но она является одним из наиболее часто неправильно понимаемых (и неправильно изучаемых) аспектов языка C. Несомненно, именно поэтому спецификации языков Java и C# устанавливают для всего определенный порядок вычислений (все операнды оцениваются слева направо, а все побочные эффекты применяются немедленно).
person
John Bode
schedule
01.06.2012