Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы.doc
Скачиваний:
48
Добавлен:
07.03.2016
Размер:
3.6 Mб
Скачать

9.3. Параметри функції та передача значень

Механізм передачі параметрів є основним способом обміну інформацією між функціями. Параметри, перераховані в заголовку опису функції, називаються формальними параметрами, або просто параметрами, а записані в операторі виклику функції – фактичними параметрами, або аргументами.

При виклику функції насамперед обчислюються вирази, що стоять на місці аргументів; потім в стеку виділяється пам'ять під формальні параметри функції відповідно до їх типу, і кожному з них привласнюється значення відповідного аргументу. При цьому перевіряється відповідність типів і при необхідності виконуються їх перетворення. При невідповідності типів видається діагностичне повідомлення.

Існує два способи передачі параметрів у функцію: за значенням та за адресою.

При передачі за значенням в стек заносяться копії значень аргументів, і оператори функції працюють з цими копіями. Доступу до початкових значень параметрів у функції немає, а, отже, немає і можливості їх змінити. При передачі за адресою в стек заносяться копії адрес аргументів, а функція здійснює доступ до елементів пам'яті по цих адресах і може змінити початкові значення аргументів:

#include <iostream>

using namespace std;

void f(int a, int* b, int& c);

void main()

{

int x = 1, y = 2, z = 3;

cout<<x<<"\t"<<y<<"\t"<<z<<"\n";

f(x, &y, z);

cout<<x<<"\t"<<y<<"\t"<<z<<"\n";

}

void f(int a, int* b, int& c)

{

a++;

(*b)++;

c++;

}

Результат виконання програми:

1 2 3

1 3 4

Перший параметр (x) передається за значенням. Його зміна у функції не впливає на початкове значення. Другий параметр (y) передається за адресою за допомогою вказівки, при цьому для передачі у функцію адреси фактичного параметра використовується операція взяття адреси, а для набуття його значення у функції потрібна операція розіменування. Третій параметр (z) передається за адресою за допомогою посилання.

При передачі по посиланню у функцію передається адреса вказаного при виклику параметра, а всередині функції всі звернення до параметра неявно розіменовуються. Тому використання посилань замість вказівок покращує читабельність програми, позбавляючи від необхідності застосовувати операції отримання адреси та розіменування. Змінна, яку приймає функція по посиланню є псевдонімом для змінної що передається. У нашому прикладі змінна c у функції є псевдонімом до змінної z, тобто

int& c = z;

Використання посилань замість передачі за значенням ефективніше, оскільки не вимагає копіювання параметрів, що має значення при передачі структур даних великого обсягу. Якщо потрібно заборонити зміну параметра всередині функції, використовується модифікатор const:

int f(const char*);

char* t(char* а, const int* b);

Рекомендується вказувати const перед всіма параметрами, зміну яких у функції не передбачено. Це полегшує налагодження великих програм, оскільки по заголовку функції можна зробити висновок про те, які величини в ній змінюються, а які ні. Крім того, на місце параметра типу const& може передаватися константа, а для змінної при необхідності виконуються перетворення типу.

Таким чином, початкові дані, які не повинні змінюватися у функції, доцільно передавати їй за допомогою константних посилань. За умовчанням параметри будь-якого типу, окрім масиву і функції, передаються у функцію за значенням.

Приведемо приклад обміну двох змінних (стопінг) різними засобами:

#include <iostream>

using namespace std;

void swap1(int x, int y);

void swap2(int* x, int* y);

void swap3(int& x, int& y);

void main()

{

int x = 1, y = 2;

cout<<x<<"\t"<<y<<"\n";

swap1(x, y);

cout<<x<<"\t"<<y<<"\n";

swap2(&x, &y);

cout<<x<<"\t"<<y<<"\n";

swap3(x, y);

cout<<x<<"\t"<<y<<"\n";

}

void swap1(int x, int y)

{

int z = x;

x = y;

y = z; //Обміну в зовнішній програмі не буде.

}

void swap2(int *x, int *y)

{

int z = *x;

*x = *y;

*y = z;

}

void swap3(int &x, int& y)

{

int z = x;

x = y;

y = z;

}

Результат виконання програми:

1 2

1 2

2 1

1 2

При використанні функції swap1 використовується передача аргументів по значенню, отже обміну не буде, стосовно функцій swap2 та swap3 – буде мати місце обмін змінних.

Передача значень за умовчанням.

З метою спрощення виклику функції, в її заголовку можна вказати значення параметрів за умовчанням. Ці параметри повинні бути останніми в списку і можуть не задаватися при виклику функції. Якщо при виклику функції параметр не вказується, мають бути пропущені і всі параметри, що стоять за ним. В якості значення параметрів за умовчанням можуть використовуватися константи, глобальні змінні та вирази:

int f1(int а, int b = 0);

void f2(int, int = 100, char* = 0);

// варіанти виклику функції f1

f1(100); f1(а, 1);

// варіанти виклику функції f2

f2(a); f2(а, 10); f2(а, 10, "Vasa");

f2(а, "Vasa") // невірно!

Функції із змінним числом параметрів.

Якщо список формальних параметрів функції закінчується багатокрапкою, це означає, що при її виклику на цьому місці можна вказати довільну кількість параметрів. Перевірка відповідності типів для цих параметрів не виконується, char і short передаються як int, а float – як double. Як приклад можна привести функцію printf, прототип якої має вигляд:

int printf (const char*, ...);

Це означає, що виклик функції повинен містити принаймні один параметр типу char* і може або містити, або не містити інші параметри:

printf("Введіть початкові дані"); // один параметр

printf("Сума: %5.2f гривень", sum); // два параметри

printf("%d %d %d", а, b, с); // три параметри

Для доступу до необов'язкових параметрів всередині функції використовуються макроси бібліотеки va_start, va_arg, та va_end, що знаходяться в заголовному файлі <stdarg.h>.

Оскільки компілятор не має інформації для контролю типів, замість функцій із змінним числом параметрів краще користуватися параметрами за .