Разыменование с помощью указателя и увеличение дает другое значение и вместо этого уменьшает его С++

Я пытался провести некоторые эксперименты с указателями на С++, я немного понял концепции приоритета, но следующая программа смешивается с моим разумом и не может ее понять.

КОД:

#include <iostream>
using namespace std;

int main() {

    int x = 9;  
    int* ptr = &x;

cout << "The value of x is " << x << endl << "The value of ptr is " << ptr << endl << *ptr << endl << (*ptr)++ << endl << (*ptr)++ << endl << (*ptr)++ << endl;

    return 0;
}

в этой программе начальное значение x равно 9, и я ожидаю, что компилятор даст мне значение x как 9, а затем увеличит его с помощью указателей, поэтому я ожидал, что ответ будет как 9, Address, 9, 10, 11, 12, но вместо этого ответ, который я получаю в каждом компиляторе, заключается в том, что значение x равно 12, а остальное похоже на это 12, Address, 11, 10, 9 Пожалуйста, помогите мне понять, что я новичок в C++


person Ali M    schedule 31.10.2020    source источник
comment
Используйте ++(*ptr) вместо (*ptr)++ для достижения желаемого результата. ++x увеличивает значение x, а затем возвращает новое увеличенное значение, а x++ увеличивает, но возвращает предыдущее значение. А по вашему вопросу вы хотели иметь поведение ++x.   -  person Arty    schedule 31.10.2020


Ответы (3)


Используйте ++(*ptr) вместо (*ptr)++ для достижения желаемого результата.

++x увеличивает значение x, а затем возвращает новое увеличенное значение, а x++ увеличивает x, но возвращает предыдущее значение (копию) x.

И в соответствии с вашими ожиданиями иметь 9, Address, 9, 10, 11, 12 вы действительно хотели иметь поведение ++x, поэтому необходимо использовать ++(*ptr).

You can see corrected code in action here online.

Обновить.

На самом деле оказалось, что один и тот же код, даже с предварительным приращением ++(*ptr), ведет себя по-разному на разных компиляторах, мой MSVC 2015 и 2019 выводит 12 addr 12 12 12 12, и если я использую флаг /std:c++latest в MSVC, то вывод будет правильным ожидаемым 9 addr 9 10 11 12, поэтому поведение изменилось в C++11 или более поздней версии. .

Таким образом, это означает, что поведение таких выражений НЕОПРЕДЕЛЕНО, что означает, что оно различно и, возможно, даже случайно на разных компиляторах.

Поэтому вам нужно определенно избегать таких выражений, если вы хотите совместимости во всех версиях компиляторов. Или используйте /std:c++latest для MSVC и аналогичные флаги для других компиляторов, чтобы принудительно использовать последний стандарт C++.

Чтобы избежать проблем, вы можете сохранять увеличенные результаты в отдельные переменные или массив, а затем выводить их в cout.

person Arty    schedule 31.10.2020
comment
Но почему он дает 12 при запуске, когда я печатаю x? он должен давать 9 при запуске, по крайней мере, поскольку на этом этапе не происходит смешивания с указателями? - person Ali M; 31.10.2020
comment
и я запустил ваш код в Visual Studio и DevC++, он по-прежнему дает то же самое, что и раньше, без изменений - person Ali M; 31.10.2020
comment
@AliM Возможно, у вас есть какая-то старая версия или очень необычный вариант компилятора, который оценивает оператор << справа налево или в каком-то другом порядке. Вы можете щелкнуть самую последнюю ссылку в моем ответе, и вы увидите, что общий компилятор, такой как Clang, выводит ожидаемый вами путь. Я предлагаю вам использовать последние версии компилятора и один из распространенных компиляторов, таких как MS Visual Studio или GCC или CLang. - person Arty; 31.10.2020
comment
@AliM Какую визуальную студию вы используете? Какая версия? Я могу проверить версии 2015 и 2019, которые есть у меня на компьютере. - person Arty; 31.10.2020
comment
@AliM Да, прошу прощения, на самом деле MSVC показывает совершенно плохие результаты как в 2015, так и в 2019 году. Это означает, что такое поведение для такого выражения НЕОПРЕДЕЛЕНО, что означает, что оно может быть случайным для разных компиляторов! Так что единственное, что нужно сделать, это не использовать ++x или x++ внутри cout << ..., вы должны сделать это приращение отдельно и только потом выводить полученное значение в cout. Вам нужно избегать таких выражений, если они разные в разных компиляторах. - person Arty; 31.10.2020
comment
@AliM На самом деле на моем компьютере MSVC 2015 и 2019 выводят 12 12 12 12 12, поэтому таких выражений UNDEFINED-behavior следует избегать. - person Arty; 31.10.2020
comment
@AliM Я нашел, как решить вашу проблему в MSVC, просто добавьте флаг /std:c++latest в командную строку вашего компилятора (команда cl). Где-то должен быть способ добавить дополнительные флаги в командную строку компилятора в вашей Dev++ IDE. - person Arty; 31.10.2020

Это не имеет ничего общего с приоритетом, но с порядком оценки. Вы предполагаете, что порядок оценки слева направо, но это не так. Как видите, в вашем случае это справа налево.

Однако это та область, в которой С++ изменился. В версии C++17 правила для выражений, подобных приведенным выше, были изменены, чтобы гарантировать порядок вычисления слева направо. Поэтому, если вы можете, используйте параметры компилятора, которые принудительно используют версию C++17, и вы должны увидеть изменение результата.

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

person john    schedule 31.10.2020

Это неопределенное поведение.

Для получения более подробной информации вы можете перейти к этому сообщению: Что сделало i = i++ + 1; законно в C++17?

person guapi    schedule 31.10.2020
comment
@user4581301 Я разместил более подробный пост - person guapi; 31.10.2020