Функція —
це іменована логічно завершена сукупність оголошень і операторів, призначених
для виконання певної задачі.
Програма мовою С містить одну або декілька функцій, кожна
з яких повинна бути оголошена та визначена до її першого використання. Оголошення функції
(прототип, заголовок) задає ім’я функції, тип значення, що повертає функція
(якщо воно є), а також імена та типи аргументів, які можуть передаватися як у
функцію, так і з неї.
Визначення функції — це задання способу виконання операцій.
Слід нагадати, що серед функцій програми повинна бути
одна з ім’ям main
(головна функція), яка може знаходитися в будь−якому
місці програми. Ця функція виконується завжди першою і закінчується останньою.
Усі функції мають однакову структуру визначення у
вигляді:
[тип результату] ім'я функції ([список формальних
аргументів])
{ // тіло функції
опис даних;
оператори;
[return] [вираз];
};
де тип результату — будь−який базовий або раніше
описаний тип значення (за винятком масиву і функції), що повертається функцією
(необов’язковий параметр). За відсутності цього параметра тип результату за
замовчуванням буде цілий (int). Він також може бути описаний ключовим
словом (void), тоді функція не повертає ніякого значення. Якщо
результат повертається функцією, то в тілі функції є необхідним оператор return
вираз;, де вираз формує значення, що співпадає з типом результату;
ім’я функції —
ідентифікатор функції, за яким завжди знаходиться пара круглих дужок «( )», де записуються формальні аргументи.
Фактично ім’я функції
— це особливий вид покажчика на функцію, його значенням є адреса початку входу
у функцію;
список формальних аргументів —
визначає кількість, тип і порядок проходження переданих у функцію вхідних
аргументів, які розділяються комою («,»).
У випадку, коли параметри відсутні, дужки залишаються порожніми або містять
ключове слово (void).
Формальні параметри функції локалізовані в ній і недоступні для будь−яких
інших функцій.
Список формальних аргументів має такий вигляд:
([const] тип 1 [параметр 1], [const] тип 2 [параметр
2], . . .)
У списку формальних аргументів для кожного параметра
треба вказати його тип
(не можна групувати параметри одного типу, вказавши їх тип один раз).
Тіло функції може складатися з описів змінних і операторів. Змінні, що
використовуються при виконанні функції, можуть бути глобальні і локальні. Змінні, що описані
(визначені) за межами функції, називають глобальними. За допомогою глобальних
параметрів можна передавати дані у функцію, не включаючи ці змінні до складу
формальних параметрів. У тілі функції їх можна змінювати і потім отримані
значення передавати в інші функції.
Змінні, що
описані у тілі функції, називаються локальними
або автоматичними. Вони існують тільки під
час роботи функції, а після реалізації функції система видаляє локальні змінні
і звільняє пам’ять. Тобто між викликами функції вміст локальних змінних
знищується, тому ініціювання локальних змінних треба робити щоразу під час
виклику функції. За необхідності збереження цих значень, їх треба описати як
статичні за допомогою службового слова static, наприклад:
static int
х, у;
або static float р = 3.25;.
Статична
змінна схожа на глобальну, але
діє тільки у тій функції, в якій вона оголошена.
На початку програми можна не описувати всю функцію, а
записати тільки прототип. Запис прототипу може містити тільки перелік типів
формальних параметрів без імен, а наприкінці прототипу завжди ставиться символ
“;»,
тоді як у описі (визначенні) функції цей символ після заголовка не присутній.
Механізм передачі параметрів є основним засобом обміну інформацією
між функцією, що викликається, та функцією, яка викликає. Параметри, котрі
зазначаються у заголовку опису функції, як відомо, називаються формальними, а
параметри, які записані у операторах виклику функції — фактичними. Наведемо
приклад фрагмента програми з використанням функцій:
double sqr (double);
//−−−−−−−−−−−−−−
прототип функції sqr()
main( )
//−−−−−−−−−−−−−−−−−−
головна функція
{
//−−−−−−−−−−−−−−−−
виклик функції sqr()
cout << "Квадрат числа=" <<
sqr (10) << endl;
}
double sqr (double p)
//−−−−−−−−−−−−−−−−−−−−−−
функція sqr()
{ return p*p; }
//−−−−−−−−−−−−−−
повернення по значенню
У результаті виконання програми буде виведено:
Квадрат
числа = 100
Функція завжди має бути визначена або оголошена до її
виклику. При
оголошенні, визначенні та виклику тієї самої функції типи та послідовність
параметрів повинні співпадати. На імена параметрів
обмежень на відповідність не існує, оскільки функцію можна викликати з різними
аргументами, а в прототипах імена ігноруються компілятором (вони необхідні
тільки для покращення читання програми). Тип значення, що повертає функція, та
типи параметрів спільно визначають тип функції.
У найпростішому випадку при виклику функції слід вказати
її ім’я, за яким у круглих дужках через кому – перелічити імена аргументів, що
передаються. Виклик функції може здійснюватися у будь−якому місці
програми, де за синтаксисом дозволяється вираз того типу, що формує функція.
Якщо тип значення, що повертає функція не void, вона може входити до складу
виразів або, у поодинокому випадку, розташовуватись у правій частині оператора
присвоювання.
У мові С визначено декілька способів передачі параметрів і повернення
результату обчислень функцій, серед них найбільш широке використання набули:
·
виклик функції з передачею параметрів за
допомогою формальних аргументів−значень;
·
виклик функції з передачею адрес за допомогою
параметрів−покажчиків;
·
виклик функцій з використанням посилань, коли
доступ до переданих параметрів забезпечується за допомогою альтернативного
імені (синоніма);
·
виклик функцій з передачею даних за допомогою
глобальних змінних;
·
виклик функцій з застосуванням параметрів, що
задані за замовчуванням, при цьому можна використовувати або всі аргументи, або
їх частину.
Виклик функції з передачею значень
полягає у тому, що у функцію передаються не самі аргументи, а їх копії. Ці
копії можна змінювати всередині функції, і це ніяк не позначиться на значеннях
аргументів, що за межами функції залишаться без зміни, наприклад:
void fun (intр)
//−−−−−−−−−−−
функція fun()
{++p;
cout << " p = " << p <<
endl; }
void main ( ) //−−−−−−−−−−−
головна функція
{ int x = 10;
fun (x); //−−−−−−−−−−−
виклик функції
cout << "x = " << x <<
endl; }
Результат
роботи цього фрагмента програми:
р=11,
х=10,
оскільки для виклику функції fun(x) до неї передається
копія значення, що дорівнює 10.
Всередині функції значення копії змінної збільшується на 1, тобто (++р), і тому
виводиться
р = = 11,
але за межами функції параметр р
не змінюється. У цьому випадку функція не повертає ніякого значення.
При цьому способі для звертання до функції достатньо написати її ім’я, а в
дужках — значення або перелік фактичних аргументів. Фактичні аргументи
повинні бути записані в тій же послідовності, що і формальні, і мати
відповідний тип (крім аргументів за замовчуванням і перевантажених функцій).
Якщо формальними аргументами
функції є параметри−значення і в ній не використовуються глобальні
змінні, функція може передати у викликаючу її програму лише одне значення, що
записується в операторі return. Це значення передається в місце виклику
функції. Достроковий вихід з функції можна також організувати з використанням
оператора return.
Виклик функції з використанням покажчиків забезпечує
передачу до функції не значень параметрів, а їх адреси, тому можливо міняти
значення цих змінних усередині функції і передавати за її межі (в інші
функції).
У цьому випадку для виклику функції у списку формальних
параметрів необхідно записати адресу того параметра, який слід змінити, тоді
відповідний формальний параметр матиме тип покажчика на цей параметр.
Усередині функції здійснюється розіменування параметра−покажчика та
виконання необхідних дій. Програма з використанням виклику функції з передачею
адрес за допомогою параметрів−покажчиків може мати вигляд:
// використання параметра покажчика
void fun2 (int *p)
{ ++*p;
cout << "*p = " << *p <<
endl; }
void main ( )
{ int x = 10;
fun2 (&x); //
виклик функції
cout
<< "x = "
<< x << endl;
}
У результаті буде виведена інформація:
*p = 11 і x = 11 .
Виклик функції з використанням параметра−посилання
здійснює передачу до функції не самої змінної, а тільки посилання на неї. У
цьому випадку забезпечується доступ до переданого параметра за допомогою
визначення його альтернативного імені, бо, як відомо, посилання є синонімом
імені параметра. Тоді всі дії, що відбуваються над посиланням, є діями над
самою змінною. Такий спосіб передачі параметрів і повернення результату
передбачає запис у списку фактичних параметрів імені змінної, а у списку
формальних — параметрів−посилань.
Наприклад:
//−−−−−−−−−−−−−−
використання параметра−посилання
void
fun (int &p)
//−−−−−−−−−− функція fun()
{ ++p;
cout << "p
= " << p << endl; }
void main (
)
{ int x =
10;
fun (x);
//−−−−−−−−−− виклик функції fun()
cout
<< "x=" << x << endl;
}
Одержимо результат попереднього фрагмента, тобто
р = 11 і х=11.
При застосуванні вказаних вище параметрів у функцію передаються
не значення змінних, а їхні адреси, тому можливо міняти значення цих змінних
усередині функції і передавати за її межі (в інші функції). Коли необхідно, щоб
деякі параметри не змінювали свої значення всередині функції, їх слід оголосити
як параметри−константи, використовуючи модифікатор const.
Використовувати глобальні змінні для передачі даних між
функціями дуже легко, оскільки вони видимі в усіх функціях, де описані локальні
змінні з тими ж іменами. Але такий спосіб не є поширеним, тому що ускладнює
налагодження програми та перешкоджає розташуванню функції у бібліотеці
загального використання. Слід прагнути, щоб функції були максимально
незалежними, а їхній інтерфейс повністю визначався прототипом функції. Наведемо
приклад використання глобальних змінних:
#include
< iostream.h >
int a, b, с;
// глобальні
параметри
sum ( );
//−−−−−−−−−−−
прототип
функції
main ( )
//−−−−−−−−−−−
головна
функція
{ cin >> а >>b;
sum();
//−−−−−−−−−−−
виклик
sum()
cout << с << endl;
}
sum( )
//−−−−−−−−−−−
функція
sum()
{ с = а + b; }
Аргументами (параметрами) функцій можуть бути не
тільки змінні, але й масиви. У цьому випадку можна використовувати як масиви
фіксованого розміру, так і невизначеного (масиви змінної довжини). При
застосуванні масивів фіксованої довжини в заголовку функції в списку формальних
аргументів указується тип масиву і його розмір, наприклад:
void sort (int mas[30]);
Якщо описується функція з масивом змінної довжини, то в
заголовку вказується тип масиву невизначеного розміру і обов’язково ще один
параметр, за допомогою якого задається розмірність масиву, наприклад:
void sort (int mas[ ],intn);
Всі масиви у функції передаються за адресою (як покажчики),
тому у випадку зміни масивів у функції ці зміни зберігаються при поверненні у
викликаючу функцію.
Наведемо приклад використання глобальних змінних для
передачі даних у процесі роботи функції.
Приклад.У масива
хm1(10),m2(15),m3(12)визначити мінімальний елемент та його індекс.
/*визначення мінімального значення кількох
масивів,використання глобальної змінної*/
#include <iostream.h>
#include <conio.h>
int
ind=0;//−−−−−−−−−−−−−−−−−−−−−−−−−−глобальна змінна
//−−−−−−−−−−−−−−−−−−−функція вводу елементів массива vvod()
vvod(float mas[ ],int n)
{ for (int і = 0; і <n ;i++)
{ cout<<"Введіть"<<і <<" елемент ";
сіn>>mas [і]; }
cout<<endl;
}
//−−−−−−−−−−−−−−−функція визначення минім. елемента —fmin()
float fmin(float mas[ ],int
n)
{ ind = 0; float min
=mas[0];
for (int і = 1; і < n; i++)
if (mas[i] <min)
{ min = mas[i]; ind = i;
}
return min;
}
//−−−−−−−−−−−−−−−головна функція
main()
{
float ml[5], m2[6], m3[7];
cout« "*****Введіть масив m1\n";
vvod(ml,5);//виклик функції vvod()— ввід масива m1[]
//виклик функції fmin()
cout<<"min1 =
"<<fmin (m1,5);
cout<<" ind =
"<<ind<<endl;
cout<<"*****Введіть масив m2\n";
vvod(m2,6);//ввід масива m2[]
cout<<"min2 =
"<<fmin (m2,6)<<endl;
cout<<" ind =
"<<ind<<endl;
cout<<"*****Введіть масив m3\n";
vvod(m3,7);//ввід масива т3[]
cout<<"min3="fmin(m3,7)<<endl;
cout<<"ind="<<ind<<endl;
getch();
}
Програма, крім головної функції main(),має також функцію vvod()введення елементів деякого формального масиву та функцію fmin() визначення мінімального елемента цього масиву. У головній функції здійснюється виклик
функцій для розв’язання необхідних обчислень кожного конкретного масиву, для
передачі параметрів використовується глобальна змінна.
Приклад .Навести
приклад програмної реалізації, в якій відбувається передача символьного масиву
у функцію.
//використання масивів як параметрів функції
#include <iostream.h>
#include <string.h>
#include <conio.h>
void fun1 (char
st[5]);//−−−−−−−−−прототип функції fun1()
main()
{
char p[5] ="файл"; fun1 (p);
cout <<"p =
" <<p <<endl;//p="диск"
getch();
return 0;
}
void fun1 (char
st[5])//−−−−−−−−−−функція fun1()
{
cout <<"p =
" <<st <<endl;//р="файл"strcpy (st,"диск");
}
Параметрами функцій можуть бути не тільки одновимірні, але й багатовимірні масиви.Уцьому випадку використовуються масиви як фіксованої розмірності, так і невизначеної довжини.
У заголовку функції під час роботи з багатовимірним масивом фіксованого розміру, наприклад матриціmat(7,10),вказуються розмірності масиву, тобто:
void fun1(intmat[7][10]);
Якщо застосовується багатовимірний масив невизначеної довжини, то невизначеним може бути тільки один вимір розмірності, наприклад:
void fun2 (int mat[][10],
int rows, int cob);
Масиви у функції можуть передаватися також за допомогою
покажчиків. У цьому випадку функція повинна мати опис покажчика на той тип
даних, елементами якого є масив, а у викликаючій функції достатньо вказати
лише ім’я масиву (як відомо, у мові С ім’я масиву є адресою цього масиву).