Студенту >> Язык программирования Си


Передача аргументов в функцию

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

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

Рассмотренный алгоритм вызова функции гарантирует сохранение значений фактических параметров независимо от того, что делала функция с соответствующими формальными параметрами. Рассмотрим функцию Sum(), вычисляющую значение суммы элементов массива:

       #include <stdio.h>

       double Sum(double A[], int nA)
       {
          double s = 0;
          while(nA) s += A[--nA];
          return s;
       }

       void main (void)
       {
          double B[] = { 1, 2, 3, 4, 5 };
          int nB = sizeof(B)/sizeof(B[0]);
          printf("Сумма = %lf\n", Sum(B,nB));
          printf("nB = %d\n", nB);
       }

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

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

       double Sum(double A[], int nA)
       {
          double s = 0, *Aend = A + nA;
          while( A < Aend ) s += *(A++);
          return s;
       }

Соответствующий фактический параметр - константный адрес массива B в вызывающей функции не меняет своего значения, то есть никаких противоречий в предыдущей функции нет.

Вообще говоря, для формальных параметров-массивов описания в виде A[] и *A совершенно идентичны и обозначают локальную копию адреса соответствующего типа. Какое из этих описаний использовать, зависит от смысла параметра. Если это массив, то более наглядно использовать описание вида A[].

НАВЕРХ