Слайд 1Взаємодія фактичних і формальних параметрів функції.
  При звертанні до
                                                            
                                    
функції всі її формальні параметри 
отримають значення відповідних фактичних параметрів.
                                    
Кількість фактичних параметрів повинна строго відповідати
 кількості формальних. Самі ж фактичні параметри можуть бути
 довільними виразами, але значення яких має бути сумісним з 
типом відповідного формального параметра (сумісність 
означає, що значення виразу може бути перетворене до типу 
формального параметра). В тілі функції опрацьовуються копії 
значень фактичних параметрів, занесені в стек, а значення 
самих фактичних параметрів при цьому не змінюються.
                                
                            							
							
							
						 
											
                            Слайд 2   
  Розглянемо функцію, яка визначає найбільше
                                                            
                                    
з трьох заданих
дійсних значень:
 double Max ( double x, double
                                    y , double z)
  {
    x = ( x > y ) ? x : y ;
    return ( x > z ) ? x : z ;
  }
 У разі наступного оголошення змінних і звертання до функції
    double u, max ;
    max = Max ( u, 50, u*u/25 );
формальний параметр x функції отримає значення змінної u, 
параметр y – значення константи 50.0, а параметр z – значення 
виразу u*u/25 . Всі три значення будуть перетворені до типу 
double. 
                                
                            							
														
						 
											
                            Слайд 3  
  Такий взаємозв’язок параметрів називають звертанням 
за
                                                            
                                    
значенням (call by value ). У тілі функції параметр x
                                    
змінюється, проте ці зміни не впливають на значення u .
   Приклад функції, яка мала би міняти місцями значення 
двох аргументів:
   void Swap1 ( int a, int b )
   {
    int d = a ;
    a = b ;  b = d ;
   }
                                
                            							
														
						 
											
                            Слайд 4  
   Якщо цю функцію викликати наступним
                                                            
                                    
чином:
   int al = 25 , bet =
                                    18 ;
   Swap1 ( al, bet ) ;
то значення  al і  bet не зміняться, хоча в тілі функції 
формальні параметри обмінюються значеннями ( це не впливає 
на значення фактичних параметрів ).
   Щоб функція могла змінити значення змінної, треба передати 
у функцію адресу цієї змінної. Тоді з функції можна буде 
звертатись до змінної за адресою та оперувати безпосередньо з 
її значенням, а не з копією, занесеною в стек. Відповідний 
формальний параметр повинен бути вказівником, базовий тип 
якого збігається з типом змінної.
  
                                
                            							
														
						 
											
                            Слайд 5  
  Таку організацію взаємозв’язку параметрів називають 
звертанням
                                                            
                                    
через посилання  ( call by reference ). 
 
                                    Приклад – стандартна функція введення scanf ( ).
  Запишемо правильний варіант функції обміну:
   void Swap2 ( int *pa, int *pb )
    {
      int d = *pa ;
     *pa = *pb ;  *pb = d ;
    }
  Звертання         Swap2 ( &al, &bet ) ;
                                
                            							
														
						 
											
                            Слайд 6Передача параметрів 
    Усі параметри, за винятком
                                                            
                                    
параметрів типу покажчик та масивів, передаються за значенням. Це означає,
                                    що при виклику функції їй передаються тільки значення змінних. Сама функція не в змозі змінити цих значень у викликаючій функції.  Наступний приклад це демонструє:
    # include 
  void test ( int a) 
  {
      a=15;
      printf (" in test : a==%d\n", a);
  }
                                
                            							
														
						 
											
                            Слайд 7  
  void main () 
{
    int a =10;
    printf
                                                            
                                    
("before test : a==%d\n", a);
    test (a);
    printf ("after test : a==%d\n",
                                    a);
}
     При передачі параметрів за значенням у функції 
утворюється локальна копія, що приводить до збільшення 
об'єму необхідної пам'яті. При виклику функції стек 
відводить пам'ять для локальних копій параметрів, а при 
виході з функції ця пам'ять звільняється. Цей спосіб 
використання пам'яті не тільки потребує додаткового її 
об'єму, але й віднімає додатковий час для зчитування. 
                                
                            							
														
						 
											
                            Слайд 8Масиви та символьні рядки як параметри функцій.
  Якщо у
                                                            
                                    
функцію передається ім’я масиву, то на відміну від
змінних інших типів
                                    не створюється копія масиву, а 
передається адреса його першого елемента. Тому функція 
здійснює роботу з тим масивом, який задано через фактичний 
параметр.
  Використовуються дві рівнозначні форми оголошення 
формального параметру – вказівника на початок масиву
 тип_елементів ім’я_масиву [ ] (наприклад int vect [ ] )
 тип_елементів * ім’я_вказівника  (наприклад int * pv) 
    
                                
                            							
														
						 
											
                            Слайд 9  
   Проілюструємо обидві форми прикладами функцій
                                                            
                                    
Average1( ) та Average2( ), кожна з яких обчислює середнє
                                    
значення n послідовних елементів масиву дійсних чисел.
 double Average1 ( double mas [ ], int n ) 
 {
   int i ;
   double sum = 0 ;
   for ( i = 0 ; i    sum += mas [ i ] ;
   return sum / n ;
 }
                                
                            							
														
						 
											
                            Слайд 10  
double Average2 ( double *pa, int n )
                                                            
                                    
 {
  int i ;
  double *pn, sum
                                    = 0 ;
  for ( pn = pa + n ; pa
    sum += *pa ;
  return sum / n ;
 }
                                 
                            							
														
						 
											
                            Слайд 11   
 Звертання до описаних вище функцій буде
                                                            
                                    
однаковим
  double arr [ 150 ], ar1, ar2 ;
                                     ……………………….
 ar1 = Average1 ( arr, 150 ) ; /* ar1= Average2 ( arr,150 )*/
 ar2 = Average2 ( &arr[ 10 ], 40 ) ;
  Змінна ar1 отримає середнє значення всіх 150 елементів 
масиву, змінна ar2 – середнє значення елементів масиву, які 
мають індекси від 10 до 49.
  Все сказане про параметри–масиви цілком стосується і тих 
параметрів функцій, які є символьними рядками. Їх можна 
оголошувати як масиви або як вказівники – остання форма на 
практиці використовується частіше.
  
                                
                            							
														
						 
											
                            Слайд 12Створення у функції нового масиву.
  Значення, яке повертає функція,
                                                            
                                    
не може бути масивом чи 
символьним рядком. Щоб сформувати у
                                    функції новий масив 
чи символьний рядок, треба виділити місце для нього у 
викликаючій функції та включити до списку параметрів 
функції, яка формує масив ( рядок ), адресу виділеної для 
нього ділянки.
  Інші варіанти – створення нового масиву ( рядка ) в 
динамічній пам’яті, або використання глобальних масивів і 
рядків ( проте вони не захищені від випадкових змін, оскільки 
до них можна звертатись з кожної точки програми).
  
                                
                            							
														
						 
											
                            Слайд 13  
  Приклад – функція, яка виділяє та
                                                            
                                    
повертає перше слово 
заданого речення. Аргументами функції є адреси 
фактичних
                                    параметрів. Така функція оперує безпосередньо 
з цими параметрами і може їх змінювати.
 #include < stdio.h>
 #include < ctype.h>
 char * FirstWord ( char * s, char * word )
 {
  char * w = word ;
  while ( isspase (* s ) ) s++ ;  /* пошук початку слова */
                                
                            							
														
						 
											
                            Слайд 14  
 while ( *s !=‘ ‘ && *s
                                                            
                                    
!=‘,’ && *s !=‘ :’ *s !=‘ .’ *s !=‘
                                    \0’ )
         * w++ = *s++;   /* копіювання першого слова */
     * w = ‘\0’ ;
  return word ;
   }
  int main ( void )
 {
   char str [ ] = “ Наш факультет – найкращий” ;
 char wrd [25] ;
  printf (“\n Перше слово: %s \n”, FirstWord (str, wrd )) ;
  return 0 ;
 }
                                
                            							
														
						 
											
                            Слайд 15  
Результат виконання
      
                                                            
                                    
   Перше слово: Наш
 Щоб захистити значення фактичного
                                    параметра від 
випадкових змін у тілі функції, треба в оголошенні 
відповідного формального параметра вказати const . Якщо ж 
формальний параметр-вказівник оголосити const, то 
компілятор стежитиме, щоб у тілі функції значення цього 
вказівника не змінювалось.
   Щоб зробити функцію FirstWord ( ) захищеною, 
оголошення параметрів потрібно записати так:
   char * FirstWord ( const char * s, char * const word )