background image

Informatyka  1 - Pracownia 

Strona 1 z 9 

© 2011 Jarosław Forenc 

MATERIAŁY POMOCNICZE NR 7 

DO PRACOWNII Z PRZEMIOTU „INFORMATYKA 1” 

 

Funkcje 



 

W programie w języku C zawsze występuje co najmniej jedna funkcja - main()



 

Od funkcji main() rozpoczyna się wykonanie całego programu.  



 

Oprócz niej mogą występować także inne funkcje zdefiniowane przez użytkownika. 



 

Ogólna struktura funkcji w języku C jest następująca: 

 

float add(float a, float b)

{

   float y;

   y = a + b;

   return y;

}

argumenty

przekazywane  do funkcji

nazwa funkcji

typ wartości

zwracanej

przez funkcję

instrukcja

nagłówek funkcji

ciało funkcji

wartość zwracana

przez funkcję

instrukcja
instrukcja

 

 
 

Przykład nr 8.1 

Funkcja dodająca dwie liczby. 

 

#include <stdio.h> 
#include <conio.h> 
 
float add(float a, float b) 

   float y; 
   y = a + b; 
   return y; 

 
int main() 

   float x1=10.0, x2=20.0, wynik; 
 
   wynik = add(x1,x2); 
   printf("Wynik = %f\n", wynik); 
 
   getch() 
   return 0; 

 

 



 

Wykonanie powyższego programu rozpoczyna się od funkcji main()

Informatyka  1 - Pracownia 

Strona 2 z 9 

© 2011 Jarosław Forenc 



 

Gdy  dochodzimy  do  instrukcji  zawierającej  funkcję  add(),  to  wywołanie  tej  funkcji 
powoduje przekazanie sterowania do jej pierwszej instrukcji. 



 

Do  funkcji  add()  przekazywane  są  dwa  parametry  typu  float.  Pierwszy  parametr  (a
otrzymuje  wartość  pierwszego  parametru  wywołania  funkcji  (x1),  natomiast  drugi 
parametr (b) - wartość drugiego parametru wywołania funkcji (x2). 



 

Powrót  z  funkcji  (do  miejsca  zaraz  po  jej  wywołaniu)  następuje  na  skutek  wykonania 
instrukcji return



 

Wartość zwracana przez funkcję podstawiana jest pod zmienną wynik



 

Po  słowie  return  może  występować  dowolne  wyrażenie.  Wyrażenie  to  często 
umieszczane jest w nawiasach, ale nie jest to konieczne. 



 

Funkcję add() można zapisać w prostszy sposób: 

float add(float a, float b) 

     return (a+b); 



 

W  wywołaniu  funkcji  jako  parametry  mogą  występować  zmienne,  wyrażenia 
arytmetyczne lub stałe liczbowe, np. 

wynik = add(10,20); 
wynik = add(x1*20+4,x1/x2); 



 

Istnieją funkcje, które nie zwracają żadnej wartości, wtedy jako typ zwracanego wyniku 
podajemy void, np. 

void drukuj(int a) 

     printf(“Liczba a wynosi: %d \n”,a); 
     return; 



 

Wywołanie takiej funkcji w programie ma postać:        

drukuj(-10);

 



 

Powyższa funkcja nie zwraca żadnego wyniku więc wystarczy samo słowo return. Jeśli 
funkcja  nie  zwraca  wyniku  i  nie  ma  w  jej  ciele  return  to  sterowanie  wraca  do  punktu 
wywołania na skutek zakończenia wykonania wszystkich instrukcji w bloku funkcyjnym. 



 

Mogą istnieć funkcje, do których nie przekazujemy żadnych parametrów formalnych, np. 

void linia() 

     printf(”----------\n”);

                lub

 

}

 

void linia(void) 

     printf(”----------\n”); 
}

 



 

Wywołanie takich funkcji w programie ma postać:       

linia();

     - nawiasy są konieczne. 



 

Ale już zapis: 

linia(void) 

     printf(”----------\n”); 

background image

Informatyka  1 - Pracownia 

Strona 3 z 9 

© 2011 Jarosław Forenc 

nie  jest  równoważny  powyższym  zapisom,  gdyż  jeśli  nie  podamy  typu  zwracanej 
wartości przez funkcję, to domyślnie jest to typ int

 
 

Umieszczanie definicji funkcji w programie 



 

Definicje  funkcji  można  umieszczać  w  dowolnym  miejscu  programu  -  przed  lub  po 
funkcji main(). Należy jednak pamiętać o tym, że zasięg widzialności funkcji rozpoczyna 
się od miejsca jej deklaracji. 



 

Jeśli  chcemy  umieścić  definicję  funkcji  po  funkcji  main(),  czyli  po  miejscu,  w  którym 
jest wywoływana, to musimy wcześniej podać jej formalną deklarację czyli prototyp



 

Prototyp  opisuje  to  samo  co  nagłówek,  ale  kończy  się  średnikiem.  W  prototypie  nie 
musimy podawać nazw argumentów formalnych - wystarczą tylko typy.  



 

Podanie nazw argumentów ma jednak znaczenie dla czytelności programu.  



 

Dzięki prototypom kompilator ma możliwość sprawdzenia zgodności typów formalnych  
i faktycznych. 



 

Rozpatrzmy strukturę następujących dwóch programów: 

#include … 
 
void fun(int a, int b); 
 
int main() 

     … 
     fun(a,b); 
     … 

 
void fun (int a, int b)       

     … 

 

#include … 
 
void fun (int a, int b) 

     … 

 
int main() 

     … 
     fun(a,b); 
     … 

 

 



 

W programie po lewej stronie funkcja fun() zdefiniowana jest po funkcji main(), dlatego 
przed  funkcją  main()  umieszczony  jest  prototyp  funkcji  fun(),  który  może  mieć  jedną  
z dwu postaci: 

void fun(int a, int b);   

lub

 

 

void fun(int, int); 



 

W programie po prawej stronie umieszczenie prototypu funkcji fun() nie jest konieczne, 
gdyż definicja funkcji fun() umieszczona jest przed funkcją main(). 

 
 

Przekazywanie parametrów do funkcji przez wartość 



 

Przekazywanie  parametrów  przez  wartość  oznacza,  że  po  przekazaniu  sterowania  do 
funkcji  tworzone  są  kopie  zmiennych  przekazywanych  do  funkcji  i  wszystkie  działania  
w funkcji wykonywane są na kopiach. 

Informatyka  1 - Pracownia 

Strona 4 z 9 

© 2011 Jarosław Forenc 

Przykład nr 8.2 

Przekazywanie parametrów do funkcji przez wartość. 

 

#include <stdio.h> 
#include <conio.h> 
 
void fun(

int a

int b


   printf("fun1:  a=%3d, b=%3d \n",

a

,

b

); 

   

a

 = 10; 

   

b

 = 10; 

   printf("fun2:  a=%3d, b=%3d \n",

a

,

b

); 


 
int main() 

   int 

a

 = 20, 

b

 = 20; 

 
   printf("main1: a = %3d, b = %3d \n",

a

,

b

); 

   fun(

a

,

b

); 

   printf("main2: a = %3d, b = %3d \n",

a

,

b

); 

 
   getch(); 
   return 0; 

 

 



 

Wynik działania programu: 

   main1: a = 20, b = 20 
   fun1:  a = 20, b = 20 
   fun2:  a = 10, b = 10 
   main2: a = 

20

, b = 

20

 



 

Po  powrocie  z  funkcji  fun()  wartości  zmiennych  a  i  b  nie  zmieniły  się,  gdyż  w  funkcji 
fun() pracowaliśmy na ich kopiach (posiadających takie same nazwy). 

 
 

Przekazywanie parametrów do funkcji przez wskaźnik 



 

Przekazywanie  parametrów  do  funkcji  przez  wskaźnik  polega  na  tym,  że  do  funkcji 
przekazywane są adresy zmiennych. Wszystkie operacje w funkcji wykonywane są zatem 
na zmiennych z funkcji wywołującej (poprzez adres tych zmiennych).  

Przykład nr 8.3 

Przekazywanie parametrów do funkcji przez wskaźnik. 

 

#include <stdio.h> 
#include <conio.h> 
 
void fun(

int *a

int *b


   printf("fun1:  a=%3d, b=%3d \n",

*a

,

*b

); 

   

*a

 = 10; 

   

*b

 = 10; 

 

background image

Informatyka  1 - Pracownia 

Strona 5 z 9 

© 2011 Jarosław Forenc 

 
   printf("fun2:  a=%3d, b=%3d \n",

*a

,

*b

); 


 
int main() 

   int 

a

 = 20, 

b

 = 20; 

 
   printf("main1: a = %3d, b = %3d \n",

a

,

b

); 

   fun(

&a

,

&b

); 

   printf("main2: a = %3d, b = %3d \n",

a

,

b

); 

 
   getch(); 
   return 0; 

 

 



 

Wynik działania programu: 

   main1: a = 20, b = 20 
   fun1:  a = 20, b = 20 
   fun2:  a = 10, b = 10 
   main2: a = 

10

, b = 

10

 



 

Po powrocie z funkcji fun() wartości zmiennych a i b zostały zmienione, gdyż do funkcji 
fun() przekazane zostały adresy zmiennych a i b (&a&b) i pracowaliśmy na zmiennych 
poprzez ich adresy. 



 

W funkcji main()

int a

- deklaracja zmiennej typu int

 

a

    

- zmienna typu int

 

&a

   

- adres zmiennej, a nie jej wartość. 



 

W funkcji fun()

int *a;

 

- deklaracja zmiennej wskaźnikowej (wskaźnik na int), 

 

a

    

- adres zmiennej typu int

 

*a

    

- wartość zmiennej wskazywanej przez a

 
 
Zmienne lokalne i zmienne globalne 



 

Zmienne  zadeklarowane  w  funkcjach  są  zmiennymi  lokalnymi  widzianymi  tylko  
w  obrębie  danej  funkcji  (bloku  funkcyjnego)  od  miejsca,  w  którym  zostały 
zadeklarowane. Zmienne lokalne są zmiennymi automatycznymi. 



 

Zmienne  zadeklarowane  poza  funkcją  main  są  zmiennymi  globalnymi  widzianymi  
w całym programie od miejsca deklaracji (są to zmienne statyczne). 



 

Jeśli zmienna globalna i lokalna mają takie same nazwy, to zmienna lokalna przesłania 
widzialność zmiennej globalnej w danej funkcji. 

 

 

 

 

 

Informatyka  1 - Pracownia 

Strona 6 z 9 

© 2011 Jarosław Forenc 

#include ... 
 
int a, b; 
 
void f1() 

     float a, c; 
     ... 

 
int main() 

     int c, d; 
     ... 
}

 

 



 

zmienne a i b typu int są zmiennymi globalnymi, 



 

zmienne a i c typu float są zmiennymi lokalnymi widzianymi 
tylko w funkcji f1()



 

zmienne c i d typu int są zmiennymi lokalnymi widzianymi 
tylko w funkcji main()



 

zmienna globalna b widziana jest w obu funkcjach: f1()  
main()



 

zmienna globalna a widziana jest tylko w funkcji main(),  
gdyż w funkcji f1() jej nazwa została przesłonięta przez 
zmienną lokalną a typu float

 

 
 
Przekazywanie tablicy jednowymiarowej (wektora) do funkcji  



 

Przy  przekazywaniu  do  funkcji  wektora,  w  nagłówku  funkcji  umieszczamy  typ 
elementów  wektora,  jego  nazwę  i  same  nawiasy  kwadratowe  lub  nawiasy  kwadratowe  
z rozmiarem wektora: 

void zeruj(int tab[]) 

 

lub

 

 

void zeruj(int tab[5]) 



 

W wywołaniu funkcji podajemy natomiast tylko nazwę wektora:  

zeruj(tab); 

Przykład nr 8.4 

Przekazywanie do funkcji tablicy jednowymiarowej (wektora). 

 

#include <stdio.h> 
#include <conio.h> 

 

void zeruj(

int tab[5]


   int i; 
   for(i=0; i<5; i++) tab[i] = 0; 

 

int main() 

   int i, tab[5] = {1,2,3,4,5}; 
 
   for(i=0; i<5; i++) printf("%3d",tab[i]); 
   printf("\n"); 
   

zeruj(tab); 

   for(i=0; i<5; i++) printf("%3d",tab[i]); 
   printf("\n"); 

 

   getch(); 
   return 0; 

 

background image

Informatyka  1 - Pracownia 

Strona 7 z 9 

© 2011 Jarosław Forenc 



 

Wynikiem działania powyższego programu jest: 

  1  2  3  4  5 
  0  0  0  0  0 



 

Do  funkcji  zeruj()  jest  przekazywany  adres  wektora.  Wszystkie  operacje  dokonane  na 
wektorze w funkcji są uwzględnione po wyjściu z niej. 

 
 
Przekazywanie tablicy dwuwymiarowej (macierzy) do funkcji  



 

Przy przekazywaniu do funkcji tablicy dwuwymiarowej musimy koniecznie podać liczbę 
wierszy i kolumn lub tylko liczbę kolumn: 

void zeruj(int tab[2][3]) 

lub

 

 

void zeruj(int tab[][3]) 



 

W wywołaniu funkcji podajemy natomiast tylko nazwę tablicy: 

zeruj(tab); 

Przykład nr 8.5 

Przekazywanie do funkcji tablicy dwuwymiarowej (macierzy). 

 

#include <stdio.h> 
#include <conio.h> 

 

void zeruj(

int tab[][3]


   int i, j; 
   for(i=0; i<2; i++)  
      for(j=0; j<3; j++) 
         tab[i][j] = 0; 

 

void drukuj(

int tab[2][3]


   int i, j; 
   for(i=0; i<2; i++)  
   { 
      for(j=0; j<3; j++) 
         printf("%3d",tab[i][j]); 
      printf("\n"); 
   } 
   printf("\n"); 

 

int main() 

   int i, j, tab[2][3] = {{1,2,3},{4,5,6}}; 

 

   drukuj(tab); 
   

zeruj(tab); 

   drukuj(tab); 

 

   getch(); 
   return 0; 

 

 

Informatyka  1 - Pracownia 

Strona 8 z 9 

© 2011 Jarosław Forenc 



 

Wynikiem działania powyższego programu jest: 

  1  2  3 
  4  5  6 

 

  0  0  0 
  0  0  0 



 

Do  funkcji  zeruj()  jest  przekazywany  adres  macierzy.  Wszystkie  operacje  dokonane  na 
macierzy w funkcji są uwzględnione po wyjściu z niej. 

 
 
Przekazywanie struktur do funkcji  



 

Struktury przekazywane są do funkcji tak jak każde inne zmienne podstawowych typów, 
czyli przez wartość. 

Przykład nr 8.6 

Program zawierający funkcję obliczającą odległość dwóch punktów. 

 

#include <stdio.h> 
#include <conio.h> 
#include <math.h> 
 
struct punkt 

   int x, y; 
}; 
 
float odleglosc(struct punkt pkt1, struct punkt pkt2) 

   return sqrt(pow(pkt2.x-pkt1.x,2)+pow(pkt2.y-pkt1.y,2)); 

 
int main() 

   struct punkt p1 = {2,3}, p2 = {-2,1}; 
   float  odl; 
    
   odl = odleglosc(p1,p2); 
   printf("Punkt nr 1: (%d,%d)\n",p1.x,p1.y); 
   printf("Punkt nr 2: (%d,%d)\n",p2.x,p2.y); 
   printf("Odleglosc = %g\n",odl); 
 
   getch(); 
   return 0; 

 

 

 
Rekurencyjne wywołanie funkcji 



 

Rekurencyjne  wywołanie  funkcji  polega  na  ponownym  jej  wywołaniu  zanim  skończyło 
się jej poprzednie wywołanie. 



 

Poniżej znajdują się trzy wersje funkcji obliczającej silnię liczby n

background image

Informatyka  1 - Pracownia 

Strona 9 z 9 

© 2011 Jarosław Forenc 

Przykład nr 8.7 (a) 

Funkcja obliczająca silnię liczby (wersja nierekurencyjna). 

 

int silnia(int n) 

    int i, wynik = 1; 

 

    for (i=1; i<=n; i++) 
        wynik = wynik * i; 
    return wynik; 

 

 

Przykład nr 8.7 (b) 

Funkcja obliczająca silnię liczby (wersja rekurencyjna). 

 

int silnia(int n) 

    if (n<=1) 
        return 1; 
    else 
        return n*silnia(n-1); 

 

 

Przykład nr 8.7 (c) 

Funkcja obliczająca silnię liczby (wersja rekurencyjna). 

 

int silnia(int n) 

    return n ? n*silnia(n-1) : 1;