Если указатель хранит адрес переменной и сам является переменной, разве он не создает бесконечные указатели и заполняет всю системную память? - PullRequest
0 голосов
/ 18 декабря 2018

Вот еще одна проблема с указателями:

Как печать чего-либо или не влияет на значение, хранящееся по определенному адресу?

lk имеет значение, равное 1, поэтому япроверка, равно ли значение, сохраненное в k + 1, 88 или нет.

#include <iostream>
int main()
{
    int i=55;
    int j=88;
    int *k=&i;
    int *l=&j;
    k++;
//  printf("%p\n",l-k); 
/*  Why does uncommenting previous line changes the output from 0 to 88?  */
    printf("%i",*k);
    return 0;
}

Ответы [ 4 ]

0 голосов
/ 18 декабря 2018

Относительно вопроса в заголовке:

Если указатель хранит адрес переменной и сам является переменной, разве он не создает бесконечные указатели и заполняет всю системную память?

Нет.Я добавил некоторый код для вывода адресов и содержимого каждого из i, j, k и l, и вот результат:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
          i  0x7ffee31d3a48   37   00   00   00    7...

          j  0x7ffee31d3a44   58   00   00   00    X...

          k  0x7ffee31d3a38   48   3a   1d   e3    H:..
             0x7ffee31d3a3c   fe   7f   00   00    ....

          l  0x7ffee31d3a30   44   3a   1d   e3    D:..
             0x7ffee31d3a34   fe   7f   00   00    ....

Надеемся, что вывод сам-объяснительно - каждая строка показывает название элемента, его адрес и его содержимое (как в шестнадцатеричном, так и в виде последовательности байтов).

Я нахожусь в системе с прямым порядком байтов, поэтому многобайтовые объекты должны читаться снизу вверх, справа налево.

В любом случае, i живет по адресу 0x7ffee31d3a48 и сохраняет значение 55 (0x37).k живет по адресу 0x7ffee31d3a38 и сохраняет значение 0x7ffee31d3a48, которое является адресом i.

Нет бесконечной регрессии адресов.k - это просто еще одна переменная - единственная разница между ней и i заключается в том, что она хранит значения другого типа.

Что касается другого вашего вопроса:

Почему раскомментирование предыдущей строки изменяет вывод с 0 на 88?

Выражение k++ меняет то, чтоk указывает на - он больше не указывает на i.Вот состояние программы после этого выражения:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
          i  0x7ffee31d3a48   37   00   00   00    7...

          j  0x7ffee31d3a44   58   00   00   00    X...

          k  0x7ffee31d3a38   4c   3a   1d   e3    L:..
             0x7ffee31d3a3c   fe   7f   00   00    ....

          l  0x7ffee31d3a30   44   3a   1d   e3    D:..
             0x7ffee31d3a34   fe   7f   00   00    ....

Вместо сохранения адреса i (0x7ffee31d3a48), k теперь сохраняет адрес 0x7ffeee31d3a4c, который ...не адрес какого-либо объекта в вашей программе.На этом этапе попытка разыменования k вызывает неопределенное поведение - ваш код может дать сбой, или вы можете получить неожиданный вывод, или каким-то чудом вы можете получить ожидаемый результат.Удаление оператора printf изменяет расположение вашей программы в памяти, что влияет на то, на что k указывает после выражения k++.

0 голосов
/ 18 декабря 2018

Если раскомментирование строки влияет на вывод, вероятно, ваш код имеет неопределенное поведение.Что ясно из фактического чтения кода, особенно этих двух строк.

С этой строкой все в порядке.

int *k=&i;

Но что вы ожидаете от этой строки?

k++;

i - это единичное int, поэтому k указывает на int после того, как оно не имеет смысла или использования, так как вы можете получить доступ к любой части памяти, что очевидно из того факта, что иногда вы получаете 0, а иногдаполучите 88.

0 голосов
/ 18 декабря 2018

В то время как

k++;

разрешено (вам разрешено устанавливать указатель после адреса скаляра и читать это значение указателя), поведение последующих разыменование из k равно не определено .Несколько парадоксально, но это означает, что поведение всей вашей программы не определено.

Поведение l-k также будет неопределенным.Арифметика указателей, включая разницу между двумя указателями, определяется только в массивах.Для этого объект можно рассматривать как массив из одного элемента.

0 голосов
/ 18 декабря 2018

На самом деле, это неопределенное поведение.Это здесь:

k++;

Увеличивает указатель, чтобы он указывал на другую область памяти, он увеличивает его на размер int.Если бы i был массивом из нескольких целых чисел, он указывал бы на следующий в строке.Но это не так, поэтому чтение из этого указателя в распечатке позже является неопределенным поведением, и оно может считываться из неуказанного места.

Когда я пробую эту программу в MSVC, она не печатает 0 или88, он печатает -858993460 каждый раз.Другой компилятор может напечатать что-то совсем другое, что-то, что изменится, или просто вывести программу из строя, или даже сделать что-то отличное от всех этих.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...