Измените указатель на массив, чтобы получить определенный элемент массива

Я понимаю общий смысл указателей и ссылок(или, по крайней мере, я думаю, что знаю), я также понимаю, что когда я использую новая Я динамически выделяю память.

мой вопрос заключается в следующем:

если бы я использовал cout << &p, он отобразит "местоположение виртуальной памяти"p. Есть ли способ, которым я мог бы манипулировать этим "местоположением виртуальной памяти"?"

например, следующий код показывает массив ints.

если бы я хотел показать значение p[1] и я знал "местоположение виртуальной памяти"p, мог бы я как-нибудь сделать "&p + 1" и получить значение p[1] С cout << *p, который теперь будет указывать на второй элемент массива?

int *p;
p = new int[3];

p[0] = 13;
p[1] = 54;
p[2] = 42;

5 ответов


конечно, вы можете манипулировать указателем для доступа к различным элементам массива, но вам нужно будет манипулировать содержимым указателя (т. е. адресом того, на что указывает p), а не адресом самого указателя.

int *p = new int[3];
p[0] = 13;
p[1] = 54;
p[2] = 42;

cout << *p << ' ' << *(p+1) << ' ' << *(p+2);

каждое сложение (или вычитание) означает последующий (предыдущий) элемент в массиве. Если p указывает на переменную 4 байта (например,int на типичных 32-битных ПК) по адресу скажем 12345, p+1 будет указывать на 12349, а не 12346. Примечание. Вы хотите изменить значение того, что содержит p, прежде чем разыменовать его для доступа к тому, на что он указывает.


не совсем. &p адрес указатель p. &p+1 будет ссылаться на адрес, который является одним int* дальше. Что вы хотите сделать, это

p=p+1; /* or ++p or p++ */

теперь, когда ты

cout << *p;

вы получите 54. Разница в том,p содержит адрес начала массива ints, а &p - это адрес p. Чтобы переместить один элемент, вам нужно указать дальше в int array, не дальше по стеку, где p жизнь.

если бы вы только &p тогда вам нужно будет сделать следующее:

int **q = &p; /* q now points to p */
*q = *q+1;
cout << *p;

, что также выведет 54 если я не ошибаюсь.


прошло некоторое время (много лет) с тех пор, как я работал с указателями, но я знаю, что если p указывает на начало массива (т. е. p[0]), и вы увеличили его (т. е. p++), то p теперь будет указывать на p[1].

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

So *p = 33 с изменением p[0] на 33.

Я предполагаю, что для получения второго элемента вы будете использовать *(p+1), поэтому синтаксис вам нужно было бы:

cout << *(p+1)

или

cout << *(++p)

Мне нравится это делать:

&p[1]

для меня это выглядит аккуратнее.


подумайте о "типах указателей" в C и C++ как о закладке очень длинного, логического строки ячеек накладывается на байта в пространстве памяти процессора, начиная с байта 0. Ширина каждой ячейки в байтах зависит от "типа" указатель. Каждый тип указателя откладывает строку с различной шириной ячеек. А "int *" указатель кладет ряд 4-байтовых ячеек, так как ширина хранения int составляет 4 байта. А "double *" кладет 8-байтовую строку на ячейку; a "struct foo *" указатель кладет строка с каждой ячейкой шириной одного "struct foo", что бы это ни было. "Адрес" любой "вещи" - это смещение байта, начинающееся с 0, ячейки в строке, содержащей"вещь".

арифметика указателя основана на ячейках в строке, а не на байтах. "*(p+10) " является ссылкой на 10-ю ячейку после "p", где размер ячейки определяется типом p. Если тип " p " - "int", адрес "p+10" - 40 байт после p; если P-указатель на структуру длиной 1000 байт, " p+10" 10,000 байт после p. (Обратите внимание, что компилятор выбирает оптимальный размер для структуры, которая может быть больше, чем вы думаете; это связано с "заполнением" и "выравниванием". Обсуждаемая структура 1000 байт может занимать 1024 байта на ячейку, например, поэтому" p+10 " на самом деле будет 10,240 байта после p.)