WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
1
PODSTAWY
PROGRAMOWANIA
Wykład 6
PROWADZĄCY: dr inż. Marcin Głowacki
Pok.907 C-5
Wrocław 2014
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
2
6.
ZASIĘG DOSTĘPNOŚCI ZMIENNYCH:
Zmienne:
Globalne
– mają zasięg ogólny – dostępne wszędzie w programie, posiadają rezerwację w
pamięci operacyjnej i swój stały adres
Lokalne
– powoływane do życia wewnątrz funkcji, znikają po zakończeniu funkcji
(tworzone tymczasowo na stosie w pamięci operacyjnej). Przesłaniają inne zmienne o tych
samych nazwach (patrz przykład)
Statyczne
– definiowane wewnątrz funkcji – zachowują wartość do następnego wywołania
tej samej funkcji
PRZESŁANIANIE ZMIENNYCH GLOBALNYCH:
Nazewnictwo zmiennych lokalnych nie jest dowolne, ponieważ zmienne globalne o tych
samych nazwach zostają
przesłonięte
przez nowe definicje, ale ich czas życia jest ograniczony
do wnętrza funkcji. Po zakończeniu funkcji zmienne lokalne znikają bezpowrotnie. Bierze się to
stąd, że są one tworzone tymczasowe na strukturze stosu w pamięci operacyjnej komputera.
Przykładowy program:
#include <iostream>
int
k
=50,
j
=10;
//zmienne globalne z nadaną wartością początkową
int
fnFunkcja
(
void
) {
return (
k
+100);
//obszar zasięgu zmiennej globalnej
k
=150
}
int main() {
using std::cout; using std::endl;
int
k
=3;
//zmienna lokalna
k
w funkcji main
cout<< ”Dla lokalnego k: ”<<
k
+100+
j
<<” Dla globalnego k: „<<
fnFunkcja()
+
j
<<endl;
}
Wynik : ? >
113, 160
<
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
3
Przykładowy program:
#include <iostream>
int
i
=10,
j
=200,
k
=300;
//zmienne globalne
void
fnFun
(
void
) {
using std::cout; using std::endl;
int
i
=4;
//przesłonięcie nazwy globalnej
static
int
j
=0;
//przesłonięcie nazwy globalnej – zmienna
static
i
++;
j
++;
k
++;
cout<<"W fnFun(): I= "<<
i
<<" J= "<<
j
<<" K= "<<
k
<<endl;
}
int main() {
int
i
,
k
=0;
for (
i
=0;
i
<3;
i
++)
fnFun
();
cout<<"W main(): I= "<<
i
<<" J= "<<
j
<<" K= "<<
k
<<endl;
return 0;
}
Wynik:
W fnFun(): I= 5 J= 1 K= 301
W fnFun(): I= 5 J= 2 K= 302
W fnFun(): I= 5 J= 3 K= 303
W main(): I= 3 J= 200 K= 0
int main() {
int i, k=0;
for (i=0; i<3; i++) fnFun();
cout<<"W main(): I= "<<i
<<" J= "<<j<<" K= "<<k<<endl;
return 0;
}
STOS
...
i
Adres
wyj
RAM
powrót
k
...
i=10
j=200
k=300
zmienne
globalne
void fnFun(void) {
using std::cout; using std::endl;
int i =4;
static int j=0;
i++; j++;k++;
cout<<"W fnFun(): I= "<<i
<<" J= "<<j<<" K= "<<k<<endl;
}
Adres
powrotu z fnFun()
i
STOS
...
i
Adres
wyj
k
...
j
j
i
i
k
skok
powrót
skok
zmienne
lokalne
zmienne
lokalne
static j=10
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
4
ARGUMENTY FUNKCJI -
przekazywanie argumentów przez wartość
Funkcja nie może wpływać na wartości zmiennych przekazywanych do funkcji jako
argumenty, ponieważ w trakcie wywołanie funkcji powoływane są do życia zmienna w sensie
lokalnym o typie i nazwie argumentu wywołania oraz z wartością początkową wywołania.
Po opuszczeniu funkcji nie pozostanie ślad po argumentach i operacjach na nich wykonanych.
Funkcja może zwrócić wartość w postaci jawnej (instrukcja return) do użycia w dalszej części
programu.
Przykładowy program:
#include <iostream>
void
fnZwieksz
(
int a, int b
) {
using std::cout; using std::endl;
a+=100;
b+=200;
cout << " a: "<<a<<" b: "<<b<<endl;
}
int main(){
using std::cout; using std::endl;
int
x
=10,
y
=10;
fnZwieksz
(
x,y
); //nie spowoduje zmiany wartości
x
i
y
w funkcji main()
cout << ” x: ”<<
x
<<” y: ”<<
y
;
return 0;
}
UWAGA
: Można to obejść używając wewnątrz funkcji zmiennych globalnych, ale nie podając
ich jako argument wywołania, lecz wykonując jedynie operacje na nich.
#include <iostream>
int
x
=10,
y
=10;
//zmienne globalne
void
fnZwieksz
(
int a, int b
) {
using std::cout; using std::endl;
x=a+100;
y=b+200;
cout << " a: "<<a<<" b: "<<b<<endl;
}
int main(){
using std::cout; using std::endl;
fnZwieksz
(
x,y
); //nie spowoduje zmiany wartości
x
i
y
w funkcji main()
cout << ” x: ”<<
x
<<” y: ”<<
y
;
return 0;
}
ARGUMENTY FUNKCJI -
przekazywanie argumentów przez adres
Poprzednio poznaliśmy przekazywanie parametrów funkcji przez wartość. Były na to
przykłady, które pokazywały, że zmienne nawet o tej samej nazwie nie mają ze sobą nic
wspólnego – jedynie ich wartość przekazywana jest do wnętrza funkcji.
Wynik:
a: 110 b: 210
x: 10 y: 10
Wynik:
a: 10 b: 10
x: 110 y: 210
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
5
Przykład:
void
fnZwieksz
(
int a, int b
) {
a +=100;
b+=200;
}
Wywołanie:
int x = 10, y = 10;
fnZwieksz
(
x,y
);
//nie zmienia wartości x i y
Efekt: //bez zmian: x = 10, y=10
1. Wykorzystać
referencję
(C++) – symboliczne przekazanie adresu
Referencja jest interesującym rozszerzeniem w języku C++, która umożliwia zadeklarowanie
funkcji z argumentami, które są adresami do zmiennych – znaczek ampersand & jest symbolem
adresu. Przetwarzanie w funkcji odbędzie się na danych spod adresu wskazanego w referencji,
zatem na komórkach pamięci oryginalnych zmiennych, które były użyte przy wywołaniu funkcji,
a nie na ich kopiach tworzonych na stosie.
Przykład z referencją
void
fnZwiekszRef
(
int &a, int &b
){ // Zmienia się jedynie deklaracja funkcji z użyciem znaku &
a+=100;
b+=200;
}
Wywołanie:
int x = 10, y = 10;
fnZwiekszRef
(
x,y
); // zmienia wartość x i y
Efekt: x=110, y=210
2. Wykorzystać
wskaźniki
(C, C++) – przekazywanie adresu przez wskaźniki
(wskaźniki zostaną szerzej omówione później)
Przykład ze wskaźnikami
void
fnZwiekszInny
(
int *a, int *b
) {
*a+=100;
*b+=200;
}
Wywołanie:
int x=10, y =10;
fnZwiekszInny
(
&x,&y
); //zmienia wartość x i y
Efekt: x=110, y=210
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
6
Przykład - zamiana wartości argumentów:
void
fnZmien
(
int &a, int &b
){
int pom=b;
b=a;
a=pom;
}
Wywołanie:
int x=10, y=30;
fnZmien
(
x,y
);
Efekt: x=30, y=10
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
7
ARGUMENTY FUNKCJI main:
Argumenty funkcji
main()
są skojarzone z
parametrami
wywołania
programu
:
nazywanymi
linią komend
lub
wierszem polecenia
int
main
() lub int
main
(
void
) – bez parametrów,
int
main
(
int argc, char *argv[]
) – dwa parametry:
argc
– liczba argumentów wywołania programu (>=1)
argv
– tablica wskaźników do tekstów argumentów
//Program wypisze liczbę oraz zawartość wszystkich argumentów funkcji main()
#include <iostream>
int
main
(
int argc, char *argv[]
) {
using std::cout; using std::endl;
cout<<”Program ”<<
argv[0]
<<” ma ”<<
argc
-1<<” argumentów.”<<endl;
for(int i=1;i<
argc
;i++)
cout<<” Argument\t”<<i<<”\tto\t”<<
argv[i]
<<endl;
return 0;
}
Wywołanie programu: funkcje_5.exe argument1 argument2 argument3
Wynik:
Program ścieżka\ funkcje_5.exe ma 3 argumentów.
Argument 1 to argument1
Argument 2 to argument2
Argument 3 to argument3
Aby kontynuować, naciśnij dowolny klawisz . . .
UWAGA: Trzeba pamiętać, żeby dokonać ustawień dla linii komend w kompilatorze, np. w Dev-
C++ w okienku Compilation przycisk Parameters.
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
8
ARGUMENTY FUNKCJI Z WARTOŚCIĄ DOMYŚLNĄ
Podczas definicji funkcji można przypisać domyślne (początkowe) wartości argumentów funkcji
void
fnSuma
(
int a=10, int b=20, int c=30, int d=40
){
....
}
Wywołanie tej funkcji może się odbyć z niepełną liczbą parametrów:
fnSuma
(
1,2
); //a=1, b=2 i domyślnie c=30 i d=40
= równoważne =
fnSuma
(
1,2,30,40
);
UWAGA:
Możemy pominąć tylko
wszystkie
argumenty począwszy od tego,
którego pominiemy jako pierwszy.
WYKŁAD 6 (2014) Podstawy programowania 1
(dr.inż Marcin Głowacki)
9
PRZECIĄŻANIE FUNKCJI
Nadajemy te same nazwy funkcjom, które realizują analogiczne operacje,
ale
różniące się typem lub liczbą parametrów
- dzięki tym różnicom kompilator
rozpoznaje, którą z funkcji ma być użyta w zależności od typu wywołania.
Przykład:
//prototypy funkcji
int
polePowierzchni
(
int bokX,int bokY
);
double
polePowierzchni
(
double bokX,double bokY
);
double
polePowierzchni
(
double promien
);
int main(){
int a=5,b=4;
double c=5.8,d=3.2, r=2.11;
cout<<"Pole powierzchni z argumentami całkowitymi "<<
polePowierzchni
(
a,b
)<<'\n';
cout<<"Pole powierzchni z argumentami rzeczywistymi "<<
polePowierzchni
(
c,d
)<<endl;
cout<<"Pole powierzchni koła z argumentem rzeczywistym "<<
polePowierzchni
(
r
)<<endl;
return 0;
}
//definicja funkcji
int
polePowierzchni
(
int bokX,int bokY
){
return (bokX*bokY);
}
double
polePowierzchni
(
double bokX,double bokY
){
return (bokX*bokY);
}
double
polePowierzchni
(
double promien
){ //promień kola
return (promien*promien*3.1415);
}