Указатель - это просто обычная переменная, которая содержит адрес чего-то другого в качестве значения.Другими словами, указатель указывает на адрес, где можно найти что-то еще.Если вы обычно думаете о переменной, содержащей непосредственные значения, такие как int a = 5;
, указатель будет просто содержать адрес, где 5
хранится в памяти, например, int *b = &a;
.
Будучи нормальной переменной,сам указатель имеет адрес.Его адрес - это адрес самой переменной, а не адрес, который она хранит.Например, char buf[] = "foo", *p = buf;
создает массив buf
и назначает адрес для первого символа в buf
в качестве адреса , содержащегося в p
(например, p
указывает на первый символ в buf
).Но у p
есть адрес в памяти.Именно по адресу p
адрес первой буквы в buf
хранится в памяти.Краткий пример может помочь:
#include <stdio.h>
int main (void) {
char buf[] = "foo",
*p = buf;
printf ("address for buf : %p\n"
"address of 1st char : %p\n"
"address held by p : %p\n"
"address for p itself : %p\n",
(void*)buf, (void*)&buf[0], (void*)p, (void*)&p);
}
Пример Использование / Вывод
$ ./bin/pointeraddr
address for buf : 0x7fffbfd0e530
address of 1st char : 0x7fffbfd0e530
address held by p : 0x7fffbfd0e530
address for p itself : 0x7fffbfd0e540
Теперь давайте посмотрим ближе, что содержит указатель и адрес указателя (где чтоудержание указателя удерживается в памяти) Давайте просто для простоты будем использовать последние три числа в адресах.
Где находится массив с символом buf
, хранящийся в памяти?
+---+---+---+---+
| f | o | o | \0| buf - array of char
+---+---+---+---+
5 5 5 5
3 3 3 3
0 1 2 3
При обращении к массиву массив преобразуется в указатель на первый элемент с учетом следующего:
(p3) За исключением случаев, когда он является операндом оператора sizeof
, оператор _Alignof
, или унарный оператор '&'
, или строковый литерал , используемый для инициализации массива, выражение с типом «массив типа» преобразуетсяна выражение с типом "указатель на тип" , которое указывает на начальный элемент объекта массива и не является lvalue.
C11 Standard - 6.3.2.1Другие операнды - L-значения, массивы и обозначения функций (p3)
Какой первый символ в массиве buf
?(ответ: buf[0]
) Каков адрес первого символа (с помощью унарного оператора '&'
)?Он совпадает с адресом buf, но имеет указатель типа на символ (в отличие от buf
, который при обращении является указателем на массив из char[4]
)
А как же p
?У него есть собственный адрес, в котором хранится адрес первого символа в buf
, например,
+---+ p - pointer to char
| 5 |
| 3 | holds the address 0x7fffbfd0e530
| 0 |
+---+
5
4 stored at 0x7fffbfd0e540
0
Как получить значение (символ) по адресу, который хранится в p
?Вы используете одинарный разыменование оператор *p
.Как вы получаете адрес, удерживаемый p
?p
уже является указателем, поэтому простая оценка p
сама дает адрес, который хранится в p
, например,
char *q = p;
q
теперь содержит адрес, который хранится в p
, сохраненном в новомадрес, в котором q
создается в памяти.
Или, очень просто, распечатать адрес, который хранится в p
, который теперь также хранится в q
, просто приведите p
(или q
) к(void*)
и печать с указателем преобразования "%p"
, например,
printf ("address held by p & q : %p\n", (void*)p);
Без магии.Указатель - это просто переменная, которая содержит адрес чего-то другого в качестве значения.Как и у любой переменной, у нее есть собственный адрес.Если вы думаете об этом таким образом, вы всегда можете выяснить, что у вас есть - и что вам нужно сделать, чтобы получить значение, хранящееся по этому адресу.
Просмотрите вещи и дайте мне знать, если у вас есть дальнейшиевопросы.