Как оценить двойные указатели в c? - PullRequest
0 голосов
/ 27 октября 2018

Я изучаю c, и меня совершенно смущает вопрос о двойном указателе.

int x = 44;
int *p = &x;
int **t = &p;

bool a = (*t = &x);

Мне нужно сказать, будет ли a равным true or false, и правильный ответ будет true. Я думал, что t указывает на адрес p, а p указывает на адрес x. Я знаю, если вы введете **t, он должен указывать на адрес x, но я подумал, что если вы просто введете *t, он должен указать на адрес p. Кто-нибудь может объяснить?

Ответы [ 6 ]

0 голосов
/ 27 октября 2018

Я знаю, если вы поставите **t, он должен указывать на адрес x, но я подумал, что если вы просто введете *t, он должен указать на адрес p.

Ну, это и правильно, и неправильно.«Точка к адресу» должна читаться как «обозначить», и это правильно.


Прежде всего, вы объявили 3 переменные

int x = 42;
int *p = &x;
int **t = &p;

Теперь это можно прочитать какx - это и int, *p - это int и **t - * int.Затем мы инициализируем x для значения 42, затем p для адреса x и t для адреса p.

Учитывая

int *p = &x;

два выражения L-значения x и *p не только имеют тип int и имеют одинаковое значение;они обозначают тот же тот же объект.Так же, как 10565305 и Эми Финк назначают одного и того же пользователя.Это также называется псевдоним - *p псевдонимы x, так же как Amy Fink и User 10565305 являются вашими псевдонимами в переполнении стека (а имя x не является самим объектом, как вычеловек, а не имя).

Аналогично с int **t = &p мы теперь замечаем, что, как и выше, *t и p обозначают один и тот же объект , p,И текущим значением p s является выражение &x.Следовательно, *t == &x должно быть правдой.

Что касается типа *t s, если **t является int, то *t должно быть int * (закон сохранения звезд в указателях;), что, конечно, соответствует типуp и тип &x.

0 голосов
/ 27 октября 2018

Я думал, что t указывает на адрес p

Да.

и p указывает на адрес x

Да.

Я знаю, если вы поставите ** т, он должен указывать на адрес х

Нет, **t - это x.

но я подумал, что если вы просто поставите * t, он должен указывать на адрес p.

Нет, *t - это p.

Оператор разыменования "дает вам" указанную вещь. Следовательно, поскольку p также &x (потому что это то, что вы установили), *t == &x.

Это спорный вопрос, хотя, потому что вы на самом деле не сравнить с ==, вы назначили с =, поэтому ваше выражение в результате этого присвоения, которое &x, которая не является NULL указатель, так что все это «правда». (Только нулевой указатель преобразуется в false).

0 голосов
/ 27 октября 2018
int x = 44;

Объявляет целочисленную переменную x, в которой хранится значение 44.

int *p = &x;

Объявляет переменную целочисленного указателя с именем p, теперь p хранит адрес x.

int **t = &p;

Объявляет указатель на указатель типа int с именем t, t хранит адрес p. (У указателей тоже есть адреса)

bool a = (*t = &x);

В С;

'*' = Извлекает значение из адреса (разыменование)

'&' = Дает адрес переменной (Ссылка)

Поскольку t - указатель на значение, хранящееся в p. *t будет значением, хранящимся в p, который является адресом x. (Мы выяснили это во второй строке)

С другой стороны, поскольку & используется для переменной x. Это позволит извлечь адрес x.

Поэтому *t == &x, который устанавливает логическое значение a в true.

0 голосов
/ 27 октября 2018

Вы сказали:

Мне нужно сказать, будет ли a истинным или ложным, и правильный ответ верный.Я думал, что t указывает на адрес p, а p указывает на адрес x. Я знаю, что если вы поставите ** t, он должен указывать на адрес x , но я подумал, что если вы просто введете * t , он должен указать на адрес p .Кто-нибудь может объяснить?

Вот моя попытка объяснения:

Часть жирный - это то, где вы запутались.** t == x == * p и * t == & x == p.

** t ссылается на значение, сохраненное в адресе x, а не на сам адрес.

* t = p ссылается на адрес x, и разыменование любого из них дает вам значение x.

Это объяснение проясняет ситуацию?Я могу развернуть или создать пример программы, если это поможет.

Пример рабочего кода будет состоять в том, чтобы напечатать эти значения, чтобы получить ясность:

int x = 42;   //&x = 0x1234DEAD (or some other address, just picked one for an example)
int * p = &x; // p = 0x1234DEAD and &p = 0x5678BEEF  (agian an example address)
int **t = &p; // t = 0x5678BEEF

printf("%d and %d and %d\n",**t, *p, x); //should be 42;
printf("%p and %p\n",*t, p); //should be 0x1234DEAD;
printf("%p\n",t); //should be 0x5678BEEF;
0 голосов
/ 27 октября 2018

Первая строка объявляет переменную 'x' типа 'int' и присваивает числовому литеральному значению 44 этой переменной.

int x = 44;

Следующая строка (2) объявляет переменную 'p' типа 'указатель на int' и присваивает значение выражения '& x' (который является адресом x, указатель на int),

int *p = &x;

Следующая строка (3) объявляет переменную 't' типа указатель на, указатель на int (указатель, который содержит указатель на тип int), и назначает выражение '& p' (которое является адресом) p, указатель на int,

int **t = &p;

Переменная t является «двунаправленным указателем». Теперь наступает «хитрая часть».

Следующая строка (4) объявляет переменную 'a', которая является переменной bool (ean) (true / false), и присваивает значение выражения в правой части ('справа),' (* t = & x ) '. Скобки предназначены для того, чтобы обеспечить соблюдение предполагаемого порядка приоритета. Поэтому мы оцениваем выражение' * t = & x '.

bool a = (*t = &x);

Здесь часть 'хитрая', предоставленный код имеет оператор присваивания '='! Если бы это было сравнение, то появился бы оператор '=='. Таким образом, этот оператор берет адрес x (указатель на int) и сохраняет его в * t (местоположение, на которое указывает t, и это указатель на int).

Если бы это сравнение, выражение сравнивало бы те же значения, и было бы верно. Но это задание. И выражение присваивания возвращает присвоенное значение, которое является адресом x (указатель на x). В большинстве систем этот указатель является местом в памяти (и может быть нулевым (NULL), если переменная была сохранена по нулевому адресу).

Выражение имеет тип указатель на int, но преобразуется (приводится) в тип bool. Поскольку C рассматривает false = 0 и true, если все не равно 0, значение преобразуется из (вероятно, не NULL) указателя в int в bool (true).

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

0 голосов
/ 27 октября 2018

Это будет true.Вот объяснение:

В bool a = (*t = &x); переменная t содержит адрес p.Вы отменяете ссылку t, т. Е. *t будет указывать на содержимое, сохраненное в расположении p.

Содержимое, сохраненное в адресе p, является адресом x.Помните *p = &x.Тогда сравнение *t == &x будет верным.

В вопросе, который вы упомянули *t = &x, если это оригинальный код, он все еще верен, так как присваивание в (*t = &x); возвращает ненулевой указатель.Когда этот ненулевой указатель преобразуется в логическое значение, он становится true.

...