мета-данные страницы
Различия
Показаны различия между двумя версиями страницы.
| Следующая версия | Предыдущая версия | ||
| c:c_ultimate_guide:pointers [2025/10/10 13:41] – создано radi0dev | c:c_ultimate_guide:pointers [2025/11/09 12:07] (текущий) – внешнее изменение A User Not Logged in | ||
|---|---|---|---|
| Строка 8: | Строка 8: | ||
| </ | </ | ||
| - | Указатель должен быть того же типа, что и объект, | + | Указатель должен быть того же типа, что и объект, |
| + | |||
| + | Указателю можно присвоить (=) значение другово указателя (хранимый в нем адрес). Операции сравнения применяются только к указателям одного типа и константе NULL. | ||
| Если объект (например int) занимает в памяти больше 1 байта - указатель будет ссылаться на ячейку, | Если объект (например int) занимает в памяти больше 1 байта - указатель будет ссылаться на ячейку, | ||
| + | |||
| + | <note tip> | ||
| + | Если мы не хотим, чтобы указатель указывал на какой-то конкретный адрес, то можно присвоить ему условное нулевое значение с помощью константы NULL, которая определена в заголовочном файле stdio.h: | ||
| + | < | ||
| + | int *pa = NULL; | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Иногда требуется присвоить указателю одного типа значение указателя другого типа. В этом случае следует выполнить операцию приведения типов. | ||
| ===== Получение адреса ===== | ===== Получение адреса ===== | ||
| Строка 28: | Строка 39: | ||
| </ | </ | ||
| - | ===== Получение значения | + | таким же образом (&) можно получить |
| - | Для | + | ===== Разыменование указателя ===== |
| + | |||
| + | Для | ||
| <code c> | <code c> | ||
| #include < | #include < | ||
| Строка 44: | Строка 57: | ||
| </ | </ | ||
| + | ===== Константы ===== | ||
| + | Мы можем манипулировать значениями констант через указатели | ||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | int main(void) { | ||
| + | const int cx = 10; | ||
| + | // получаем адрес константы, | ||
| + | *(int*) &cx = 20; | ||
| + | printf(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Сам указатель тоже может быть const. Константный указатель может указывать и на обычную автоматическую переменную. Константному указателю нельзя изменить адрес, который в нем храниться, | ||
| + | |||
| + | Константный указатель на константу не может менять ни свой адрес, ни значение по адресу. | ||
| + | |||
| + | ===== Массивы указателей ===== | ||
| + | |||
| + | Массив указателей определяется одним из трех способов: | ||
| + | <code c> | ||
| + | int array[] = {1, 2, 3, 4}; | ||
| + | int *p1[3]; | ||
| + | int *p2[] = { & | ||
| + | int *p3[3] = { & | ||
| + | </ | ||
| + | |||
| + | Вместо %%*p[i]%% для доступа к элементу из array мы могли бы написать %%**(p+i)%%: | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | ===== Указатель на массив ===== | ||
| + | |||
| + | '' | ||
| + | |||
| + | <code c> | ||
| + | int array1[] = {11, 12, 13}; | ||
| + | int (*pa1)[3] = & | ||
| + | |||
| + | int array2[] = {11, 12, 13, 14, 15}; | ||
| + | int (*pa2)[] = & | ||
| + | |||
| + | int (*pa3)[3] = & | ||
| + | </ | ||
| + | |||
| + | ==== Указатель и массив строк ==== | ||
| + | |||
| + | Соответственно если указатель типа char можно представить в виде строки, | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | int main(void) { | ||
| + | char *fruit[] = {" | ||
| + | for(int i=0; i < 5; i++) { | ||
| + | printf(" | ||
| + | // аналогично | ||
| + | printf(" | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Указатели на указатели ===== | ||
| + | |||
| + | Если указатель хранит адрес переменной, | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | | ||
| + | int main(void) { | ||
| + | int x = 22; | ||
| + | int *px = &x; // указатель px хранит адрес переменной x | ||
| + | int **ppx = &px; // указатель ppx хранит адрес указателя px | ||
| + | |||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Здесь указатель ppx хранит адрес указателя px. Поэтому через выражение *ppx можно получить значение, | ||
| + | |||
| + | {{: | ||
| + | |||
| + | ===== Указатели на функцию ===== | ||
| + | |||
| + | Указатель на функцию представляет собой выражение или переменную, | ||
| + | |||
| + | общий синтаксис: | ||
| + | '' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | void hello() { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | void goodbye() { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | int sum(int x, int y) { | ||
| + | return x + y; | ||
| + | } | ||
| + | |||
| + | int subtract(int x, int y) { | ||
| + | return x - y; | ||
| + | } | ||
| + | |||
| + | int main(void) { | ||
| + | // определяем указатель на функцию | ||
| + | void (*message) (void); | ||
| + | | ||
| + | message=hello; | ||
| + | message(); // вызываем функцию, | ||
| + | message = goodbye; // указатель указывает на функцию goodbye | ||
| + | message(); // вызываем функцию, | ||
| + | | ||
| + | int a = 10; | ||
| + | int b = 5; | ||
| + | int result; | ||
| + | int (*operation)(int, | ||
| + | operation=sum; | ||
| + | result = operation(a, | ||
| + | printf(" | ||
| + | operation = subtract; | ||
| + | result = operation(a, | ||
| + | printf(" | ||
| + | | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Массивы указателей на функции ==== | ||
| + | |||
| + | '' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | void sum(int x, int y) { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | void subtract(int x, int y) { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | void multiply(int x, int y) { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | int main(void) { | ||
| + | int a = 10; | ||
| + | int b = 5; | ||
| + | void (*operations[3])(int, | ||
| + | |||
| + | // получаем длину массива | ||
| + | int length = sizeof(operations)/ | ||
| + | |||
| + | for(int i=0; i < length; i++) { | ||
| + | operations[i](a, | ||
| + | } | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||