Указатели как параметры функций.

В языке Си аргументы при стандартном вызове функции передаются по значению. Это означает, что в стеке, как и в случае локальных данных, выделяется место для формальных параметров функции. В выделенное место при вызове функции заносятся значения фактических аргументов, при этом проверяется соответствие типов и при необходимости выполняются их преобразования. При несоответствии типов выдается диагностическое сообщение. Затем функция использует и может изменять эти значения в стеке.

При выходе из функции измененные значения теряются, т.к. время жизни и зона видимости локальных параметров определяется кодом функции. Вызванная функция не может изменить значения переменных, указанных как фактические аргументы при обращении к данной функции.

В случае необходимости функцию можно использовать для изменения передаваемых ей аргументов. В этом случае в качестве аргумента необходимо в вызываемую функцию передавать не значение переменной, а ее адрес.

При передаче по адресу в стек заносятся копии адресов аргументов, а функция осуществляет доступ к ячейкам памяти по этим адресам и может изменить исходные значения аргументов. Для обращения к значению аргумента-оригинала используется операция «*».

Пример функции, в которой меняются местами значения x и y:

 

void zam(int *x, int *y)

{

int t = *x;

*x = *y;

*y = t;

}

 

Участок программы с обращением к данной функции:

 

void zam (int*, int*);

void main (void)

{

int a=2, b=3;

printf(" a = %d , b = %dn", a, b);

zam (&a, &b);

printf(" a = %d , b = %dn", a, b);

}

 

При таком способе передачи данных в функцию, их значения будут изменены, т.е. на экран монитора будет выведено:

a = 2 , b=3

a = 3 , b=2

 

Если требуется запретить изменение значений, адресуемых каким-либо параметром внутри функции, то в его декларации используют атрибут const, например:

void f1(int, const double *);

Рекомендуется указывать const перед всеми параметрами - указателями, для которых в функции не предусмотрено изменение значений, на которые они ссылаются. Это облегчает, например, отладку программы, т.к. по заголовку функции видно, какие данные в функции изменяются, а какие нет.