Отдельно стоит сказать про указатели на константы и константные указатели.
Кроме переменных в программе на Си для хранения данных могут использоваться константы, которые предваряются ключевым словом const, и указатели также могут указывать на константы, но в этом случае перед определением указателя также ставится слово const:
#include <stdio.h> int main(void) { const int a = 10; const int *pa = &a; printf("address=%p \t value=%d \n", pa, *pa); return 0; }
Здесь указатель pa
указывает на константу a
. Поэтому даже если мы захотим изменить значение по адресу, который хранится в указателе,
мы не сможем это сделать, например так:
*pa = 34;
В этом случае мы просто получим ошибку во время компиляции.
Возможна также ситуация, когда указатель на константу на самом деле указывает на переменную:
#include <stdio.h> int main(void) { int a = 10; const int *pa = &a; printf("value=%d \n", *pa); // 10 a = 22; printf("value=%d \n", *pa); // 22 //*pa = 34; // так делать нельзя return 0; }
В этом случае переменную отдельно мы сможем изменять, однако по прежнему изменить ее значение через указатель мы не сможем.
Через указатель на константу мы не можем изменять значение переменной/константы. Но мы можем присвоить указателю адрес любой другой переменной или константы:
int a = 10; const int *pa = &a; // указатель указывает на переменную a const int b = 45; pa = &b; // указатель указывает на константу b
Но также мы можем определять константные указатели. Они не могут изменять адрес, который в них хранится, но могут изменять значение по этому адресу.
int a = 10; int *const pa = &a; printf("value=%d \n", *pa); // 10 *pa = 22; // меняем значение printf("value=%d \n", *pa); // 22 int b = 45; // pa = &b; так нельзя сделать
И объединение обоих предыдущих случаев - константный указатель на константу, который не позволяет менять ни хранимый в нем адрес, ни значение по этому адресу:
int a = 10; const int *const pa = &a; //*pa = 22; так сделать нельзя int b = 45; // pa = &b; так сделать нельзя