PODSTAWY INFORMATYKI Wykład 4
Zmienne zewnętrzne i lokalne int x; /* zmienna zewnętrzna */ float func3(int z) { int x; /* zmienna lokalna */ return 3*z; } main() { int y; ....
Zmienne lokalne Zmienne zadeklarowane wewnątrz funkcji są prywatne (lokalne) dla tej funkcji Żadna inna funkcja nie ma do nich bezpośredniego dostępu Domyślnie, takie zmienne są automatyczne Zmienne automatyczne są alokowane w pamięci na czas wykonywania funkcji, potem są usuwane Nie zachowują wartości między wywołaniami funkcji Początkowo mają przypadkową wartość Zmienne lokalne mogą być też statyczne; wtedy nie są alokowane
Zmienne zewnętrzne Zmienna zewnętrzna musi zostać zdefiniowana, dokładnie raz, poza jakąkolwiek funkcją (przydział pamięci) Zmienna musi również zostać zadeklarowana w każdej funkcji, która będzie jej używała; deklaracja określa typ zmiennej Deklaracją może być jawna deklaracja extern pośrednia deklaracja - wynikająca z kontekstu; definicja jest też deklaracją, wystarczy umieścić ją przed użyciem zmiennej
Parametry i wyniki funkcji Pierwszy wiersz funkcji power, int power(int base, int n) deklaruje typy parametrów i ich nazwy oraz typ wyniku funkcji Nazwy użyte przez power dla parametrów są lokalne dla funkcji power, nie są widoczne dla żadnej innej funkcji Będziemy stosować nazwę parametr dla nazwanej zmiennej na liście parametrów funkcji. Czasem stosuje się tu też nazwę argument formalny oraz argument aktualny dla argumentu przekazywanego w wywołaniu funkcji Wartość wyznaczana przez power jest zwracana instrukcją return Funkcja nie musi zwracać wartości Zwracana wartość może zostać zignorowana
Prototypy funkcji Kompilator musi wiedzieć, że dany identyfikator oznacza funkcję, przed jej wywołaniem; musi również znać listę parametrów W języku C można: zdefiniować funkcję przed jej wywołaniem, lub zadeklarować funkcję przed jej wywołaniem stosując prototyp i zdefiniować ją później Deklaracja, nazywana prototypem funkcji, musi zgadzać się z definicją funkcji
Definicje i prototypy Definicja Prototyp ...i definicja wywołanie! float fun(int x) { return 3*x; } int main() { float w; w = fun(5); ... return 0; Prototyp ...i definicja float fun(int); int main() { float w; w = fun(5); ... return 0; } float fun(int x) { return 3*x; wywołanie! wywołanie!
Przykład funkcji temperatury #include <stdio.h> double cels(int x) { return (5.0/9.0)*(x-32);} /* print Fahrenheit-Celsius table */ main() { int fahr; for (fahr = 0; fahr<=300;fahr=fahr+20) printf("%3d %6.1lf\n", fahr, cels(fahr)); return 0; }
Przykład funkcji wypisywania znaku #include<stdio.h> #include<string.h> #include<stdlib.h> int daj_znak_a(void); int main(void) { char ch; ch=daj_znak_a(); printf("%c",ch); return 0; } int daj_znak_a(void){ return 'a'; /*WYNIK a*/
Przykład funkcji ze wskaźnikiem #include<stdio.h> #include<string.h> #include<stdlib.h> int*inic(int x); int licznik; int main(void){ int*p; p=inic(110); printf("wartosc licznik (przez wskaznik p)wynosi %d\n",*p); return 0; } int*inic(int x){ licznik=x; return &licznik; /*WYNIK wartosc licznik (przez wskaznik p)wynosi 110*/
Przykład funkcji sumy/10 #include<stdio.h> #include<string.h> #include<stdlib.h> double srd(); int main(void){ printf("%f",srd()); return 0; } double srd(){int i; double suma,num;suma=0.0; for(i=0;i<4;i++){ printf("wprowadz kolejna liczba:\n"); scanf("%lf",&num); suma=suma+num; return suma/10.0;
Wynik programu wprowadz kolejna liczba:3 wprowadz kolejna liczba:4 1.400000
Przykład funkcji wypisywania #include<stdio.h> #include<string.h> #include<stdlib.h> void f2(int b); void f1(int a); int main(void){ f1(30); return 0; } void f1(int a){ if(a)f2(a-1); printf("%d",a); void f2(int b){ printf("."); if(b)f1(b-1); /*WYNIK ...............024681012141618202224262830*/
Przykład funkcji silnia #include<stdio.h> #include<string.h> #include<stdlib.h> int silnia(int i); int main(void){ printf("5 silnia wynosi %d",silnia(5)); return 0; } int silnia(int i){ if(i==1){return 1;} else return i*silnia(i-1); /*WYNIK 5 silnia wynosi 120*/
Przekazywanie wartości do funkcji Wszystkie argumenty są przekazywane przez wartość Wywoływana funkcja otrzymuje kopie przekazanych wartości w zmiennych lokalnych Aby uzyskać efekt przekazania argumentu przez zmienną (jak w języku Pascal), można użyć wskaźnika jako typu parametru i przekazać funkcji adres miejsca, które ma zostać zmodyfikowane
Przekazywanie wartości do funkcji Przykład: int fun5(double *w) { ... } ... fun5(&x);
Przekazywanie tablic do funkcji Po zastosowaniu nazwy tablicy jako argumentu funkcji, przekazywany jest tylko adres początkowego elementu tablicy Nie są kopiowane elementy tablicy! Więcej szczegółów o przekazywaniu tablic funkcjom: później
Konwersje typów Kiedy operator ma działać na operandach różnych typów, są one konwertowane przy zastosowaniu według niewielkiego zbioru reguł. double x, y; int k; y = x + k; Ogólnie, jedynymi automatycznymi konwersjami są takie, które przekształcają typ „mniejszy” w „większy” bez utraty informacji. Różne typy!
Konwersje typów - c.d. Wyrażenia, które nie mają sensu, są zakazane Przykład: użycie float jako indeksu Wyrażenia, w których można utracić informację, powodują zgłoszenie ostrzeżenia, ale są dozwolone; przykłady: kopiowanie większego typu całkowitego do mniejszego przypisanie wartości zmiennoprzecinkowej do zmiennej całkowitej
Konwersje typów - reguły Jeśli nie występują operandy unsigned, wystarczający jest następujący zestaw reguł: Jeśli jeden z operandów jest typu long double, przekształć drugi na long double. W przeciwnym wypadku, jeśli jeden operand jest double, przekształć drugi na double. W przeciwnym wypadku, jeśli operand jest float, przekształć drugi na float. W przeciwnym wypadku, przekształcić char i short na int. Potem, jeśli jeden z operandów jest long, przekształć drugi na long.
Wymuszanie konwersji Jawna konwersja typu może być wymuszona w wyrażenie przez zastosowanie operatora rzutowania (ang. cast) W następującej konstrukcji: (nazwa_typu) wyrażenie wyrażenie jest przekształcane na wyrażenie o podanym typie cels = ((double)5/9) * (fahr-32); Konwersje są również wykonywane w wywołaniach funkcji
Struktury Struktura jest obiektem zawierającym ciąg nazwanych składowych niekoniecznie tego samego typu Słowo struct wprowadza deklarację struktury, która jest listą deklaracji ujętą w nawiasy klamrowe Po słowie struct może wystąpić opcjonalna nazwa (structure tag) Nazwa ta opisuje ten rodzaj struktury i może zostać użyta potem jako skrót deklaracji w nawiasach Dostęp: struct-name.member Przykład: struct point { int x; int y; }k;
Struktury - szczegóły Przykład: struct point { opcjonalna nazwa int x; int y; } k; struct point v, w; v.x = 7; v.y = 9; w = v; opcjonalna nazwa składowe opcjonalne definicje zmiennych
Przypisywanie nazw typom strukturalnym typedef struct { float re, im; } tcompl; tcompl a, b, c; a.re = 10.5; a.im = 36.6; b = c = a; ...działa jak: struct compl { float re, im; }; struct compl a, b, c; a.re = 10.5; ... albo: struct { } a, b, c;
Do czego służą nazwy struktur i typedef struct { float re, im; } a, b; } c; a.re = 10.5; a.im = 36.6; c = a; struct compl { float re, im; } a, b; struct compl c; ... c = a; struct { } a, b, c; OK ZAKAZANE
Struktury przykład 1 #include<stdio.h> #include<stdlib.h> struct typ_s { int i; char ch; double d; char nap[80]; }s; int main(void){ printf("wprowadz liczbe calkowita:\n"); scanf("%d",&s.i); printf("wprowazdz znak:"); scanf("%c",&s.ch); printf("wprowadz liczbe zmiennoprzecinkowa:\n"); scanf("%lf",&s.d); printf("wprowadz napis:"); scanf("%s",s.nap); printf("%d%c%f%s",s.i,s.ch,s.d,s.nap); return 0;}
Wynik programu wprowadz liczbe calkowita:4 wprowadz napis:ttt 4 wprowazdz znak:wprowadz liczbe zmiennoprzecinkowa:4.5 wprowadz napis:ttt 4 4.500000ttt
Struktury przykład 2 /* WYNIK 10100101 */ #include<stdio.h> #include<stdlib.h> int main(void) { struct typ_s{ int i; int j; }s; i=10; s.i=100; s.j=101; printf("%d%d%d",i,s.i,s.j); return 0;} /* WYNIK 10100101 */
Struktury przykład 3 /* WYNIK 99 98.600000 */ #include<stdio.h> #include<stdlib.h> struct typ_s{ int i; double d; }; void f(struct typ_s tymcz); int main(void) { struct typ_s zmi1; zmi1.i=99; zmi1.d=98.6; f(zmi1); return 0; } void f(struct typ_s tymcz){ printf("%d %f",tymcz.i,tymcz.d); /* WYNIK 99 98.600000 */
Struktury mogą być zwracane przez funkcje typedef struct { float re, im; } cplx; cplx mult(cplx c, float x) { c.im *= x; c.re *= x; return c; }
Struktury mogą być zagnieżdżane typedef struct { char name[50]; struct { int ye, mo, da; } birthdate; } tperson; tperson p1; strcpy(p1.name,"Jan Kowalski"); p1.birthdate.ye = 1945; p1.birthdate.mo = 1; p1.birthdate.da = 17;
Tablice struktur typedef struct { double re,im; } tcplx; void test() { int i; tcplx tab[50]; for (i=0;i<50;i++) tab[i].re = tab[i].im = 0.0; }