Понимание указателей в C / C ++
Прежде чем понять, как работают указатели, необходимо понять, как переменные хранятся и доступны в программах. Каждая переменная состоит из 2 частей: (1) адрес памяти, где хранятся данные, и (2) значение хранимых данных.
Адрес памяти часто называют lvalue переменной, а значение хранимых данных называют rvalue (l и r означают левый и правый).
Рассмотрим утверждение:
int x = 10;
Внутренне программа связывает адрес памяти с переменной x. В этом случае давайте предположим, что программа назначает x для размещения по адресу 1001 (не реалистичный адрес, но выбранный для простоты). Следовательно, lvalue (адрес памяти) x равно 1001, а rvalue (значение данных) x равно 10.
Доступ к r-значению осуществляется с помощью переменной «x». Для доступа к lvalue необходим оператор «address of» (‘&’). Выражение ‘& x’ читается как «адрес x».
Expression Value
----------------------------------
x 10
&x 1001
Значение, сохраненное в x, может быть изменено в любое время (например, x = 20), но адрес x (& x) никогда не может быть изменен.
Указатель - это просто переменная, которую можно использовать для изменения другой переменной. Он делает это, имея адрес памяти для своего значения. То есть он указывает на другое место в памяти.
Создание указателя на «x» выполняется следующим образом:
int* xptr = &x;
«int *» сообщает компилятору, что мы создаем указатель на целочисленное значение. Часть «= & x» сообщает компилятору, что мы присваиваем адрес x значению xptr. Таким образом, мы сообщаем компилятору, что xptr «указывает» на x.
Предполагая, что xptr назначен адресу памяти 1002, память программы может выглядеть следующим образом:
Variable lvalue rvalue
--------------------------------------------
x 1001 10
xptr 1002 1001
Следующий фрагмент головоломки - это «оператор косвенного обращения» (‘*’), который используется следующим образом:
int y = *xptr;
Оператор косвенного обращения указывает программе интерпретировать значение xptr как адрес памяти, а не как значение данных. То есть программа ищет значение данных (10), сохраненное по адресу, предоставленному xptr (1001).
Собираем все вместе:
Expression Value
--------------------------------------------
x 10
&x 1001
xptr 1001
&xptr 1002
*xptr 10
Теперь, когда концепции были объяснены, вот код, демонстрирующий силу указателей:
int x = 10;
int *xptr = &x;
printf("x = %d\n", x);
printf("&x = %d\n", &x);
printf("xptr = %d\n", xptr);
printf("*xptr = %d\n", *xptr);
*xptr = 20;
printf("x = %d\n", x);
printf("*xptr = %d\n", *xptr);
Для вывода вы увидите (Примечание: адрес памяти будет отличаться каждый раз):
x = 10
&x = 3537176
xptr = 3537176
*xptr = 10
x = 20
*xptr = 20
Обратите внимание, как назначение значения для * xptr изменило значение x. Это связано с тем, что «* xptr» и «x» относятся к одной и той же ячейке памяти, о чем свидетельствуют «& x» и «xptr», имеющие одинаковое значение.