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

 

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

1) запись в стек копий переменных или констант, перечисленных в списке аргументов (если поле «список_аргументов» в прототипе функции не void);

2) вызов процедуры с возвратом (либо «близкий», либо «далекий» в зависимости от заданного явно или неявно типа функции).

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

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

В общем случае существуют два стиля передачи параметров функции:

1) вызов функции с передачей значений (Call-By-Value);

2) вызов функции с передачей адресов переменных (Call-By-Reference).

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

/* Prim6_2.cpp */

#include <stdio.h>

int sum( int, int);

void main( void)

{int a = 5, b = 4, c;

c = sum( a, b);

printf( "%d\n", c);

}

int sum( int k, int l)

{int m;

m = k + l;

return m;

}

Функции sum() передаются копии переменных a и b. Эти копии используются функцией в качестве значений для аргументов k и l.

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

/* Prim6_3.cpp */

#include <stdio.h>

int sum( int*, int*);

void main( void)

{int a = 5, b = 4, c;

c = sum( &a, &b);

printf( "%d\n", c);

}

int sum( int* k, int* l)

{int m;

m = *k + *l;

return m;

}

В приведенном примере в функцию передаются копии указателей на ячейки памяти (другими словами, адреса в памяти). Эти адреса используются для доступа к памяти.

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

/* Prim6_4.cpp */

char* my_strcpy( char* destination, char* source)

{char* ret_ptr = destination;

while( *source)

*destination ++= *source++;

*destination = ‘\0’; /* перенос символа ‘\0’ */

return ret_ptr;

}

Если программисту привычнее манипулировать с элементами массива, предыдущую программу можно записать так:

/* Prim6_5.cpp */

char* my_strcpy( char destination[], char source[])

{char* ret_ptr = destination;

while( *source)

*destination ++= *source++;

*destination = ‘\0’; /* перенос символа ‘\0’ */

return ret_ptr;

}

Первую строку функции my_strcpy() можно записать и так:

char* my_strcpy( char* destination, char* source)

а для доступа к элементам по-прежнему использовать индекс.

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

Ниже приводится пример функции example, которая принимает переменное число аргментов и выводит на печать их количество и принятые значения. Число действительно переданных через стек значений задает первый аргумент:

/* Prim6_6.cpp */

#include <stdio.h>

void example( int, …);

void main( void)

{int var1 = 5, var2 = 6, var3 = 7, var4 = 8, var5 = 9;

example( 2, var1); /* вызов функции с двумя аргументами */

example( 3, var1, var2); /* та же функция имеет три аргумента */

example( 6, var1, var2, var3, var4, var5); /* а теперь – шесть */

}

void example( int arg1, …)

{int* ptr = &arg1; /* установка указателя на первый аргумент */

printf("\n Функции EXAMPLE передано всего %d аргумента(ов):\n", arg1); /* печать всех переданных в функцию фактических аргументов */

for( ; arg1; arg1--) {printf("%d", *ptr); ptr++;}

 

Запуск программы на выполнение дает такие результаты:

Функции EXAMPLE передано всего 2 аргумента(ов):

2 5

Функции EXAMPLE передано всего 3 аргумента(ов):

3 5 6

Функции EXAMPLE передано всего 6 аргумента(ов):

6 5 6 7 8 9

В данном примере первый аргумент используется, как счетчик количества аргументов.

 

 








Дата добавления: 2017-01-29; просмотров: 530;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.007 сек.