Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекція 7 (Функції).docx
Скачиваний:
18
Добавлен:
16.05.2015
Размер:
74.76 Кб
Скачать

Void f(int I, int* j, int& k);

Int main()

{

int i=1,j=2,k=3;

cout <<"i j k\n";

cout<<i<<" "<<j<<" "<<k<<'\n'; // 1 2 3

f(i,&j,k);

cout<<i<<" "<<j<<" "<<k; // 1 3 4

return 0;

}

Void f(int і, int* j, int& k)

{

i++; (*j)++; k++;

}

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

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

Якщо потрібно заборонити зміну параметра усередині функції, використовується модифікатор const:

іnt f(const char*);

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

Масиви в якості параметрів функції

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

Одновимірний массив як параметр

Ім’я массиву є покажчиком на його нульовий елемент, тому у функцію масиви передаються за покажчиком. Кількість елементів массиву може передаватися окремим параметром.

Приклад. Програма підраховує, в якому з двох масивів кількість додатних елементів більша.

int n_posit(int* mas, int n);

int main()

{

int n,i;

cout<<"Input count of symbols: ";

cin>>n;

int *A = new int[n];

int *B = new int[n];

// генеруємо елементи масивів

for (i=0; i<n; i++)

{

A[i] = rand()%100 - 50;

B[i] = rand()%200 - 100;

}

// виводимо масиви на екран

cout << "\n\nA: ";

for (i=0; i<n; i++) cout << " "<<A[i];

cout << "\n\nB: ";

for (i=0; i<n; i++) cout << " "<<B[i];

// порівнюємо кількість додатних елементів

if (n_posit(A,n) > n_posit(B,n))

cout << "\n\nFirst array A is winner!";

else if (n_posit(A,n) < n_posit(B,n))

cout << "\n\nSecond array B is winner!";

else

cout << "\n\nEqual count!";

_getch();

return 0;

}

int n_posit(int* mas, int n)

{

int count = 0;

for (int i=0; i<n; i++)

if (mas[i]>0) count++;

return count;

}

Результат:

Рядок (массив символів) як параметр функції

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

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

void outMyText(char* str);

int main()

{

cout<<"\n InString: ";;

char str[80];

gets(str);

outMyText(str);

_getch();

return 0;

}

void outMyText(char* s)

{

cout << "\n\n\n OutString: ";

int i = 0;

while(s[i] != '\0')

{

cout << "__" << s[i];

i++;

}

}

Результат:

Двовимірний массив в якості параметра функції

Приклад. Виведення масиву на екран по рядках

void printArray(int** mas, int n, int m);

int main()

{

int n,m,i;

cout<<"\n Input n m: ";

cin>>n>>m;

int** A = new int*[n];

// генеруємо елементи масивів

for (i=0; i<n; i++)

{

A[i] = new int[m];

for (int j=0; j<m; j++)

A[i][j] = rand()%200 - 100;

}

printArray(A,n,m);

_getch();

return 0;

}

void printArray(int** mas, int n, int m)

{

cout << "\n\nARRAY:\n\n";

for (int i=0; i<n; i++)

{

cout<<"\n";

for (int j=0;j<m;j++)

printf("%6i",mas[i][j]);

}

}

Результат:

Передача параметрів функції main

Функція main, з якої починається виконання СІ-програми, може бути визначена з параметрами, які передаються з зовнішнього оточення, наприклад, з командного рядка.

У зовнішньому оточенні діють свої правила подання даних, а точніше, всі дані представляються у вигляді рядків символів. Для передачі цих рядків у функцію main використовуються два параметри, перший параметр служить для передачі числа переданих рядків, другий для передачі самих рядків. Загальноприйняті (але не обов'язкові) імена цих параметрів argc і argv. Параметр argc має тип int, його значення формується з аналізу командного рядка і дорівнює кількості слів у командному рядку, включаючи і ім'я програми (під словом розуміється будь-який текст не містить символу пробіл). Параметр argv це масив покажчиків на рядки, кожна з яких містить одне слово з командного рядка. Якщо слово повинно містити символ пробіл, то при записі його в командний рядок воно має бути вкладенo в лапки.

Функція main може мати і третій параметр, який прийнято називати argp, і який служить для передачі у функцію main параметрів операційної системи (середовища) в якій виконується СІ-програма. Заголовок функції main має вигляд:

int main (int argc, char * argv [], char * argp [])

Якщо, наприклад, командний рядок СІ-програми має вигляд:

A: \> cprog working 'C program' 1

то аргументи argc, argv, argp представляються в пам'яті як показано в схемі :

argc [ 4 ]

argv [ ]--> [ ]--> [A:\cprog.exe\0]

[ ]--> [working\0]

[ ]--> [C program\0]

[ ]--> [1\0]

[NULL]

argp [ ]--> [ ]--> [path=A:\;C:\\0]

[ ]--> [lib=D:\LIB\0]

[ ]--> [include=D:\INCLUDE\0]

[ ]--> [conspec=C:\COMMAND.COM\]

[NULL]

Операційна система підтримує передачу значень для параметрів argc, argv, argp, а на користувача лежить відповідальність за передачу і використання фактичних аргументів функції main.

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

int main ( int argc, char *argv[], char *argp[])

{ int i=0;

printf ("\n Имя программы %s", argv[0]);

for (i=1; i<=argc; i++)

printf ("\n аргумент %d равен %s",i, argv[i]);

printf ("\n Параметры операционной системы:");

return (0);

}

Вбудовувані функції (inline-функції)

В результаті роботи компілятора кожна функція представляється у вигляді машинного коду. Якщо в програмі виклик функції зустрічається декілька разів, в місцях таких звернень генеруються коди виклику вже реалізованого примірника функції. Однак виконання викликів вимагає деякої витрати часу. Таким чином, якщо тіло функції невеликого розміру і звернення до неї в програмі відбувається досить часто, на практиці можна вказати компілятору замість викликів функції в відповідних місцях генерувати все її тіло. Здійснюється це за допомогою ключового слова inline. Тим самим збільшується продуктивність реалізованого коду, хоча, звичайно, розмір програми може збільшуватися. Компілятори різних фірм накладають свої обмеження на використання вбудовуваних функцій, тому перед використанням inline- функцій необхідно звернутися до керівництва компілятора. Ключове слово inline повинно передувати першому виклику вбудованої функції (наприклад, міститися в її прототипі).

#include <iostream>

using namespace std;

inline int Sum(int, int);

int main(){

int A=2, B=6, C=3;

char eol = '\n';

cout << Sum(A,B) << eol;

cout << Sum(B,C) << eol;

cout << Sum(A,C) << eol;

return 0;

}

int Sum(int x, int у) {

return x + у;

}

У наведеному прикладі в кожному місці виклику функції Sum() буде згенеровані її код.

Класи пам'яті

      Будь-яка змінна та функція, описана y програмі на Сi, належить до конкретного класу пам'яті, що визначає:

  • час її існування - це період, протягом якого змінна існує в пам'яті,

  • область видимості (область дії) - це частина програми, в якій змінна може використовуватися.

В мові Сі існує чотири специфікатори класу пам'яті: auto, register, extern і static.

Клас пам'яті

Ключове слово

Час існування

Область дії

Автоматичний

auto

тимчасово

блок

Регістровий

register

тимчасово

блок

Статичний локальний

static

постійно

блок

Статичний глобальний

static

постійно

файл

Зовнішній

extern

постійно

програма

      Клас пам'яті для функції завжди external, якщо перед її описом не стоїть специфікатор static. Клас пам'яті конкретної змінної залежить або від місця розташування її опису, або задається явно за допомогою спеціального специфікатору класу пам'яті, що розташовується перед описом функції. Усі змінні Сі можна віднести до одного з наступних класів пам'яті:

auto (автоматична, локальна)

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