У C, функція — це еквівалент підпрограм чи функцій Fortran, або процедур чи функцій Pascal. Функції забезпечують зручним способом герметизувати, або відокремити, якесь обчислення, яке після того можна використати не хвилюючись про те, як саме воно було втілене. Із добре спроектованими функціями, можна не звертати уваги, як саме вирішено проблему; знання того, що саме зроблено — вистачить. C робить використання функцій легким, зручним і ефективним; ви часто побачите короткі функції, означені та викликані тільки один раз лише тому, що вони прояснюють якийсь кусочок коду.
Досі ми використовували тільки такі функції як printf, getchar і putchar, які нам було надано; тепер час написати декілька власних. Оскільки C не має експоненційного оператора **, як у Fortran, дозвольте нам продемонструвати механіку визначення функції шляхом написання власної power(m,n), яка зводить ціле m до додатнього чілочисельного степеню n. Тобто, значенням power(2,5) буде 32. Ця функція не є практичною рутиною зведення до степеню, оскільки вона оперує лише додатними показниками степеня з невеликими значеннями, але вона підходить для ілюстрації. (Стандартна бібліотека містить функцію pow(x,y), яка обчислює xy.)
Наступне — це функція power разом із main для її виклику, тож ви можете побачити всю структуру зразу.
#include <stdio.h>
int power(int m, int n);
/* випробовування функції power */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3,i));
return 0;
}
/* power: зводить base до n-ного степеня; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
Визначення функції має таку форму:
тип_повернення назва_функції(оголошення параметрів, якщо є)
{
оголошення
твердження
}
Визначення функцій можуть з'являтися в будь-якій послідовності, в одному вихідному файлі або в багатьох, за умови, що функцію не розщеплено по різних файлах. Якщо вихідний текст програми розбито на декілька файлів, вам, можливо, доведеться здійснити додаткові дії, щоб скомпілювати та завантажити її, ніж коли все знаходиться в одному, але це залежить від операційної системи, а не властивостей мови. Наразі, ми припустимо, що обидві функції знаходяться у тому самому файлі, тож все, чого ви навчилися про запуск C-програм, працюватиме. Функцію power викликано двічі всередині main у рядкові
printf("%d %d %d\n", i, power(2,i), power(-3,i));
Кожний виклик передає два аргументи функції power, яка, в свою чергу, повертає ціле для форматування і виводу. Всередині виразу power(2,i) є цілим, так само як 2 та i. (Не всі функції видають ціле значення; ми розглянемо це питання у Розділі 4.)
Перший рядок самої power
int power(int base, int n)
оголошує типи параметрів та їхні назви, і тип результату, який функція поверне. Назви, використані power для свої параметрів, являються локальними для power, і не видимі для будь-якої іншої функції — інші функції можуть скористатися з тих самих назв, не викликаючи конфліктів. Те саме стосується змінних i та p — змінна i з power не має жодного стосунку доi з main.
Ми, загалом, користуватимося словом «параметр» для назв змінних функції зі списку в круглих дужках. Терміни «формальний аргумент» і «дійсний аргумент» також іноді використовуються для такого розрізнення.
Значення, обчислене power, передається main за допомогою твердження return. Будь-який вираз може слідувати за return:
return вираз;
Функції не обов'язково мають повертати якесь значення; твердження return без якогось виразу передає контроль, але жодного корисного значення, викликачеві, так само як «падіння з кінця» функції, коли досягнуто кінцевої фігурної дужки. Викликова функція також може проігнорувати значення, повернене викликаною.
Ви, можливо, помітили return укінці main. Оскільки main — це така сама функція, як і будь-яка інша, вона також може повертати значення викликачеві, що насправді є середовищем у якому запущено програму. Типово, повернення нуля означає нормальне завершення; ненульові значення сигналізують незвичайні або помилкові умови завершення. Дотепер, ми, для спрощення, опускали твердження return всередині main, але надалі ми включатимемо його, як нагадування, що програми мають повертати середовищу свій статус.
Оголошення
int power(int base, int n);
перед самою main вказує на те, що power — це функція, що очікує два аргументи типу int і повертає один int. Це оголошення, яке називається прототипом функції, має збігатися з визначенням і використанням power. Це спричинить помилку, якщо визначення функції або якийсь випадок її використання не зійдеться з прототипом.
Назви параметрів не мусять співпадати. Насправді, назви параметрів не обов'язкові в прототипі функції, тож його можна написати як
int power(int, int);
Вдало вибрані імена змінних — це хороша підказка, однак, тож ми часто їх використовуватимемо. Історична примітка: найбільшою зміною між ANSI C і ранніми версіями є спосіб в який функції оголошено і означено. В оригінальній версії C, функцію power було би написано так:
/* power: зводить base до n-ного степеня; n >= 0 */
/* (старий стиль) */
power(base, n)
int base, n;
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
Параметри вказано всередині круглих дужок, а їхні типи — перед відкриттям фігурних; неоголошені параметри вважаються за int. (Корпус функції такий самий як і у попередньому прикладі.)
Оголошення power напочатку програми виглядало би так:
int power();
Список параметрів був неможливим, тож компілятор не міг одразу перевірити, чи power буде викликано належним чином. Насправді, оскільки power без задання всерівно повернуло би int, оголошення можна було би опустити взагалі.
Новий синтаксис прототипів функцій набагато полегшує компілятору виявлення помилок у кількості аргументів або їхніх типах. Старий стиль оголошень і визначень ще працює в ANSI C, принаймні протягом перехідного періоду, але ми настійно рекомендуємо, щоб ви вживали нову форму, якщо ваш компілятор її підтримує.
Вправа 1-15. Перепишіть заново програму перетворення температур з Розділу 1.2 з використанням функції для перетворень.