Найти в Дзене
LITVINOV-UPGRADE-LINUX

C++ - неопределенное поведение при множественном изменении одной и той же переменной в выражении.

В с++ есть некоторое количество случаев когда, не определен точный порядок операций и в зависимости от реализации компилятора или стандарта можно получить разный результат. Рассмотрим простой пример: #include <iostream>
int main()
{
int i = 1;
printf("%d, %d\n", i++, i++);
return 0;
} Вопрос простой, что будет выведено в результате работы программы? printf является функцией, соответственно очередность выполнения выражений в аргументах не определена, можно получить результат: 1, 2 или 2, 1 и даже 1, 1 Этот эксперимент можно повторить на платформе https://godbolt.org Результат 2, 1 Результат 1, 2 Причем будет выдано предупреждение: warning: multiple unsequenced modifications to 'i' [-Wunsequenced] -Wunsequenced - возникает, когда в одном выражении происходит несколько изменений одной и той же переменной, причем порядок их выполнения не определен. В C/C++ стандарт не гарантирует, в каком порядке будут вычисляться такие операции, что может привести к неожиданным результатам. Получи
Оглавление

Вступление

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

Рассмотрим простой пример:

#include <iostream>
int main()
{
int i = 1;
printf("%d, %d\n", i++, i++);
return 0;
}

Вопрос простой, что будет выведено в результате работы программы?

printf является функцией, соответственно очередность выполнения выражений в аргументах не определена, можно получить результат: 1, 2 или 2, 1 и даже 1, 1

Этот эксперимент можно повторить на платформе https://godbolt.org

GCC 15.1

Результат 2, 1

Clang

Результат 1, 2

Причем будет выдано предупреждение: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]

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

Получился случай идентичный по сути такой записи:

i = i++ + ++i; // UB: два изменения `i` в одном выражении

-2

MSVC v19

Результат 1, 1

Причем при изменении стандарта на с++17 ('/std:c++17)

Результат 2, 1

ответ на этот вопрос дает блог компании PVS-Studio (https://pvs-studio.ru/ru/blog/posts/cpp/0722/)

-3
-4

Далее цитата:

в стандарт C++17 было дописано следующее:

The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.

Компилятор все так же имеет право вычислять аргументы в произвольном порядке, но теперь, начиная со стандарта C++17, к вычислению следующего аргумента и его побочным эффектам имеет право приступить лишь с того момента, как будут выполнены все вычисления и побочные эффекты предыдущего аргумента.

Ссылки:

Для проверки статьи и ассемблерного кода

Compiler Explorer

Статья первоисточник

Глубина кроличьей норы или собеседование по C++ в компании PVS-Studio