Указатель Арифметический Инкремент пост / префикса
У меня возникают проблемы с выполнением логики определенного фрагмента кода ниже.
int i[] = { 21, 4, -17, 45 };
int* i_ptr = i;
std::cout << (*i_ptr)++ << std::endl; // 21
std::cout << *i_ptr << std::endl; // 22
std::cout << *i_ptr++ << std::endl; // 22
std::cout << *(i_ptr - 1) << std::endl; // 22
std::cout << *i_ptr << std::endl; // 4
std::cout << ++*i_ptr << std::endl; // 5
std::cout << *++i_ptr << std::endl; // -17
system("pause");
Моя проблема в том, как этот код пошел из 22...
std::cout << *(i_ptr - 1) << std::endl; // 22
До 4.
std::cout << *i_ptr << std::endl; // 4
А потом до 5.
std::cout << ++*i_ptr << std::endl; // 5
Когда я впервые просмотрел этот код, я подумал, что 22 просто переходит с 22 на 21. Я понимаю, что это связано с приоритетом оператора C++, но для меня это не имеет смысла.
4 ответа
std::cout << (*i_ptr)++ << std::endl; // 21
//i_ptr points to i[0], which is increased from 21 to 22
std::cout << *i_ptr << std::endl; // 22
//prints i[0], which is 22
std::cout << *i_ptr++ << std::endl; // 22
//prints i[0] and increments i_ptr to point to i[1]
std::cout << *(i_ptr - 1) << std::endl; // 22
//prints i[0], i_ptr points to i[1], so i_ptr - 1 points to i[0]
std::cout << *i_ptr << std::endl; // 4
//prints i[1], which is 4
std::cout << ++*i_ptr << std::endl; // 5
//prints the incremented i[1], which was 4 and is 5 now
std::cout << *++i_ptr << std::endl; // -17
//increment i_ptr to point to i[2] and prints the value
Выражение *i_ptr++
увеличивает указатель Это указывает на второй элемент массива (со значением 4
).
Это, конечно, означает, что i_ptr - 1
должен указывать на элемент до того, где i_ptr
в данный момент указывает, который является первым элементом (со значением 22
).
И помните, для любого указателя или массива p
и индекс i
Выражения p[i]
а также *(p + 1)
точно равны
Еще один способ увидеть это, вы начинаете с
+-----+-----+-----+-----+ | 21 | 4 | -17 | 45 | +-----+-----+-----+-----+ ^ | i_ptr
Вы тогда делаете (*i_ptr)++
который увеличивает значение где i_ptr
указывает:
+ ----- + ----- + ----- + ----- + | 22 | 4 | -17 | 45 | + ----- + ----- + ----- + ----- + ^ | i_ptr
Тогда вы делаете *i_ptr++
который первым разыменовывает старую ценность i_ptr
(что приводит к 22
), а затем увеличить указатель:
+ ----- + ----- + ----- + ----- + | 22 | 4 | -17 | 45 | + ----- + ----- + ----- + ----- + ^ | i_ptr
А теперь ты делаешь в основном i_ptr[-1]
:
+ ----- + ----- + ----- + ----- + | 22 | 4 | -17 | 45 | + ----- + ----- + ----- + ----- + ^ ^ | | | i_ptr | i_ptr - 1
Отрицательные индексы в порядке и четко определены, если они не выходят за пределы.
Это связано с этими тремя строчками:
std::cout << *i_ptr++ << std::endl; // 22
std::court << *(i_ptr - 1) << std::endl; // 22
std::cout << *i_ptr << std::endl; // 4
Вот что происходит:
std::cout << *i_ptr++ << std::endl; // 22
Здесь это интерпретируется как *(i_ptr++)
, что означает "продвигать ptr вперед, чтобы указывать на следующий элемент, а затем возвращать указатель туда, где раньше указывал i_ptr, и интерпретировать это". Другими словами, после завершения выполнения этой строки указатель ptr указывает на элемент 4, но строка печатает 22, потому что именно там раньше указывал ptr. Это важно, поскольку это означает, что мы изменили то, что ищем, хотя результаты не сразу это подтверждают.
Давайте посмотрим на следующую строку:
std:: cout << * (i_ptr - 1) << std:: endl; // 22
Это говорит: "распечатайте элемент на одну точку раньше, где i_ptr смотрит". Помните, что в данный момент i_ptr смотрит на 4, поэтому, посмотрев один элемент назад в списке, мы увидим значение 22.
Наконец, мы делаем это:
std::cout << *i_ptr << std::endl; // 4
Это говорит: "распечатайте все, на что смотрит i_ptr". Так как мы смотрим на 4 - и уже некоторое время - вот что мы видим здесь.
Уже после этой строки
std::cout << *i_ptr++ << std::endl; // 22
i_ptr
указывает на 4
, Таким образом, в следующей строке, когда вы печатаете один элемент, прежде чем вы получите снова 22
:
std::cout << *(i_ptr - 1) << std::endl; // 22
и сейчас i_ptr
по-прежнему указывает на 4
:
std::cout << *i_ptr << std::endl; // 4