Руководство полного чайника по программированию на языке Си

       

* 18_POINTERS.txt *


УКАЗАТЕЛИ ========= void f(int x){ x = 7; }

main(){ int y = 17; f(y); printf("y=%d\n", y); /* печатает: y=17 */ }

В аргументе x передаётся КОПИЯ значения y, поэтому x=7; не изменяет значения у. Как все же сделать, чтобы вызываемая функция могла изменять значение переменной?

Отбросим два способа:

- объявление y как глобальной (много глобальных переменных - плохой стиль),

- y=f(y); (а что если надо изменить МНОГО переменных? return, к несчастью, может вернуть лишь одно значение).

Используется новая для нас конструкция: УКАЗАТЕЛЬ.

Пример (@)

void f(int *ptr){ /* #2 */ *ptr = 7; /* #3 */ }

main (){ int y=17;

f(&y); /* #1 */ printf("y=%d\n", y); /* печатает: y=7 */ }

Ну как, нашли три отличия от исходного текста?

Мы вводим две новые конструкции:

&y "указатель на переменную y" или "адрес переменной y"

*ptr означает "разыменование указателя ptr" (подробнее - позже)

int *ptr; означает объявление переменной ptr, которая может содержать в себе указатель на переменную, хранящую int-число.

Для начала определим, что такое указатель.

int var1, var2, z; /* целочисленные переменные */ int *pointer; /* указатель на целочисленную переменную */

var1 = 12; var2 = 43; pointer = &var1;

Мы будем изображать указатель в виде СТРЕЛКИ; это хороший прием и при практическом программировании. ________ /pointer/ _/_______/_ | значение| Переменная, хранящая указатель | есть | (адрес другой переменной) | | | &var1 | | | |_______|_| | |&var1 - сам указатель на var1 - | "стрелка, указывающая на переменную var1". V Она обозначается &var1 ________ / var1 / _/_______/_ | значение| | есть | | 12 | |_________|

Таким образом, УКАЗАТЕЛЬ - это "стрелка, указывающая на некий ящик-переменную". Начало этой стрелки можно (в свою очередь) хранить в какой-нибудь переменной.

При этом, если стрелка указывает на переменную типа int, то тип переменной, хранящей начало стрелки, есть int *

Если типа char, то тип - char *

АДРЕС (указатель на) можно взять только от переменной или элемента массива, но не от выражения.

int x; int arr[5];

Законно &x стрелка на ящик "x" & arr[3] стрелка на ящик "arr[3]"

Незаконно &(2+2) тут нет именованного "ящика", на который указывает стрелка, да и вообще ящика нет.



Содержание раздела