Операции с указателями
Указатели в языке Си поддерживают ряд операций: присваивание, получение адреса указателя, получение значения по указателю, некоторые арифметические операции и операции сравнения.
Присваивание
Указателю можно присвоить либо адрес объекта того же типа, либо значение другого указателя или константу NULL.
Присвоение указателю адреса уже рассматривалось в прошлой теме. Для получения адреса объекта используется операция &:
1
2
int a = 10;
int *pa = &a; // указатель pa хранит адрес переменной a
Причем указатель и переменная должны иметь тот же тип, в данном случае int.
Присвоение указателю другого указателя:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 2;
int *pa = &a;
int *pb = &b;
printf("Variable a: address=%p \t value=%d \n", pa, *pa);
printf("Variable b: address=%p \t value=%d \n", pb, *pb);
pa = pb; // теперь указатель pa хранит адрес переменной b
printf("Variable b: address=%p \t value=%d \n", pa, *pa);
return 0;
}
Когда указателю присваивается другой указатель, то фактически первый указатель начинает также указывать на тот же адрес, на который указывает второй указатель.
Если мы не хотим, чтобы указатель указывал на какой-то конкретный адрес, то можно присвоить ему условное нулевое значение с помощью константы NULL, которая определена в заголовочном файле stdio.h:
1
int *pa = NULL;
Разыменование указателя
Операция разыменования указателя в виде *имя_указателя, позволяет получить объект по адресу, который хранится в указателе.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main(void)
{
int a = 10;
int *pa = &a;
int *pb = pa;
*pa = 25;
printf("Value on pointer pa: %d \n", *pa); // 25
printf("Value on pointer pb: %d \n", *pb); // 25
printf("Value of variable a: %d \n", a); // 25
return 0;
}
Через выражение *pa мы можем получить значение по адресу, который хранится в указателе pa, а через выражение типа *pa = значение вложить по этому адресу новое значение.
И так как в данном случае указатель pa указывает на переменную a, то при изменении значения по адресу, на который указывает указатель, также изменится и значение переменной a.
Адрес указателя
Указатель хранит адрес переменной, и по этому адресу мы можем получить значение этой переменной. Но кроме того, указатель, как и любая переменная, сам имеет адрес, по которому он располагается в памяти. Этот адрес можно получить также через операцию &:
1
2
3
4
5
int a = 10;
int *pa = &a;
printf("address of pointer=%p \n", &pa); // адрес указателя
printf("address stored in pointer=%p \n", pa); // адрес, который хранится в указателе - адрес переменной a
printf("value on pointer=%d \n", *pa); // значение по адресу в указателе - значение переменной a
Операции сравнения
К указателям могут применяться операции сравнения >, >=, <, <=,==, !=. Операции сравнения применяются только к указателям одного типа и константе NULL. Для сравнения используются номера адресов:
1
2
3
4
5
6
7
8
int a = 10;
int b = 20;
int *pa = &a;
int *pb = &b;
if(pa > pb)
printf("pa (%p) is greater than pb (%p) \n", pa, pb);
else
printf("pa (%p) is less or equal pb (%p) \n", pa, pb);
Консольный вывод в моем случае:
pa (0060FEA4) is greater than pb (0060FEA0)
Приведение типов
Иногда требуется присвоить указателю одного типа значение указателя другого типа. В этом случае следует выполнить операцию приведения типов:
1
2
3
4
5
char c = 'N';
char *pc = &c;
int *pd = (int *)pc;
printf("pc=%p \n", pc);
printf("pd=%p \n", pd);