LEKCJA 15. Jak posługiwać się funkcjami. ________________________________________________________________ W trakcie tej lekcji dowiesz się więcej o: * funkcjach i prototypach funkcji; * przekazywaniu argumentów funkcji; * współpracy funkcji ze wskaźnikami. _______________________________________________________________ Aby przedstawić działanie operatorów logicznych opracujemy własną funkcję Demo() i zastosujemy ją w programie przykładowym [najważniejszy fragment]. int Demo(int Liczba) { int MaxNr=15; for (; MaxNr>=0; MaxNr--) { if ((Liczba>>MaxNr)&1) printf("1"); else printf("0"); } return 0; //Funkcja nie musi nic zwracac } Funkcja przesuwa liczbę o kolejno 15, 14, 13 itd. bitów w prawo i sprawdza, czy 16, 15, 14 bit jest jedynką, czy zerem. Iloczyn logiczny z jedynką ( 0000000000000001 ) gwarantuje nam, że wpływ na wynik operacji będzie miał tylko ten jeden bit (patrz wyżej - jak działają operatory logiczne). [P042.CPP] # include int Demo(int Liczba) { int MaxNr=15; for (; MaxNr>=0; MaxNr--) if ((Liczba>>MaxNr)&1) printf("1"); else printf("0"); return 0; } char odp; int main() { int X, Y; clrscr(); printf("\nPodaj dwie liczby calkowite od -32768 do +32767\n"); printf("\nLiczby X i Y rozdziel spacja"); printf("\nPo podaniu drugiej liczby nacisnij [Enter]"); printf("\nLiczby ujemne sa w kodzie dopelniajacym"); printf("\nskrajny lewy bit oznacza znak 0-Plus, 1-Minus"); for(;;) { printf("\n"); scanf("%d %d", &X, &Y); printf("\nX:\t"); Demo(X); printf("\nY:\t"); Demo(Y); printf("\n~Y:\t"); Demo(~Y); printf("\nX&Y:\t"); Demo(X&Y); printf("\nX|Y:\t"); Demo(X|Y); printf("\nX^Y:\t"); Demo(X^Y); printf("\nY:\t"); Demo(Y); printf("\nY>>1:\t"); Demo(Y>>1); printf("\nY<<2:\t"); Demo(Y<<2); printf("\n\n Jeszcze raz? T/N"); odp=getch(); if (odp!='T'&& odp!='t') break; } return 0; } Jeśli operacje mają być wykonywane nie na bitach a na logicznej wartości wyrażeń: || oznacza sumę (LUB); && oznacza iloczyn (I); ! oznacza negację (NIE). Przykłady: (x==0 || x>5) - x równa się 0 LUB x większy niż 5; (a>5 && a!=11) - a większe niż 5 I a nie równe 11; (num>=5 && num!=6 || a>0) num nie mniejsze niż 5 I num nie równe 6 LUB a dodatnie; Wyrażenia logiczne sprawdzane instrukcją if MUSZĄ być ujęte w nawiasy okrągłe. Do wytworzenia wartości logicznej wyrażenia może zostać użyty operator relacji: < <= == >= > != . Jeśli tak się nie stanie, za wartość logiczną wyrażenia przyjmowane jest: 1, PRAWDA, TRUE, jeśli wartość numeryczna wyrażenia jest różna od zera. 0, FAŁSZ, FALSE, jeśli wartość numeryczna wyrażenia jest równa zero. Porównaj: if (a<=0) ... if (a) ... if (a+b) ... Konwersja - przykłady. C++ dysponuje wieloma funkcjami wykonującymi takie działania, np: itoa() - Integer TO Ascii - zamiana liczby typu int na łańcuch znaków ASCII; ltoa() - Long int TO Ascii - zamiana long int -> ASCII; atoi() - zamiana Ascii -> int; atol() - zamiana Asdii -> long int . Wszystkie wymienione funkcje przekształcając liczby na łańcuchy znaków potrzebują trzech parametrów: p1 - liczby do przekształcenia; p2 - bufora, w którym będą przechowywać wynik - łańcuch ASCII; p3 - podstawy (szesnastkowa, dziesiętna itp.). Jeśli chcemy korzystać z tych funkcji, powinniśmy dołączyć plik nagłówkowy z ich prototypami - stdlib.h (STandarD LIBrary - standardowa biblioteka). A oto przykład. [P043.CPP] # include "stdio.h" # include "stdlib.h" main() { int i; char B10[10], B2[20], B16[10]; //BUFORY for (i=1; i<17; i++) printf("%s %s %s\n", itoa(i, B10[i], 10), itoa(i, B2[i], 2), itoa(i, B16[i], 16)); return 0; } [Z] ________________________________________________________________ 1. Opracuj program testujący działanie funkcji atoi(). ________________________________________________________________ KILKA SŁÓW O TYPACH DANYCH i KONWERSJI W C/C++ . Przed przystąpieniem do obszernego zagadnienia "funkcje w C" krótko zasygnalizujemy jeszcze jedno zjawisko. Wiesz z pewnością, że wykonywane na liczbach dwójkowych mnożenie może dać wynik o długości znacznie większej niż mnożna i mnożnik. W programach może się poza tym pojawić konieczność np. mnożenia liczb zmiennoprzecinkowych przez całkowite. Jak w takich przypadkach postępuje C++ ? Po pierwsze: C/C++ może sam dokonywać konwersji, czyli zmiany typów danych naogół zgodnie z zasadą nadawania zmiennej "mniej pojemnego" rodzaju typu zmiennej "bardziej pojemnego" rodzaju przed wykonaniem operacji; Po drugie: my sami możemy zmusić C++ do zmiany typu FORSUJĄC typ świadomie w programie. W przykładzie poniżej podając w nawiasach żądany typ zmiennej forsujemy zmianę typu int na typ float. [P044.CPP] # include "stdio.h" void main() { int a=7; printf("%f", (float) a); } Konwersja typów nazywana bywa także "rzutowaniem" typów (ang. type casting). A oto kilka przykładów "forsowania typów": int a = 2; float x = 17.1, y = 8.95, z; char c; c = (char)a + (char)x; c = (char)(a + (int)x); c = (char)(a + x); c = a + x; z = (float)((int)x * (int)y); z = (float)((int)x * (int)y); z = (float)((int)(x * y)); z = x * y; c = char(a) + char(x); c = char(a + int(x)); c = char(a + x); c = a + x; z = float(int(x) * int(y)); z = float(int(x) * int(y)); z = float(int(x * y)); z = x * y; FUNKCJE BIBLIOTECZNE I WŁASNE W JĘZYKU C/C++ . Pojęcie funkcji obejmuje w C/C++ zarówno pascalowe procedury, jak i basicowe podprogramy. Funkcji zdefiniowanych w C++ przez prducenta jest bardzo dużo. Dla przykładu, funkcje arytmetyczne, które możesz wykorzystać do obliczeń numerycznych to np.: abs() - wartość bezwzględna, cos() - cosinus, sin() - sinus, tan() - tangens, asin(), atan(), acos(), - funkcje odwrotne ARCUS SINUS... funkcje hiperboliczne: sinh(), cosh(), tanh(), wykładnicze i logarytmiczne: exp() - e^x log() - logarytm naturalny, log10() - logarytm dziesiętny. Jeśli skorzystasz z systemu Help i zajrzysz do pliku math.h (Help | Index | math.h), znajdziesz tam jeszcze wiele przydatnych funkcji. Funkcja może, ale nie musi zwracać wartość do programu - dokładniej do funkcji wyższego poziomu, z której została wywołana. W ciele funkcji służy do tego instrukcja return. Użytkownik może w C++ definiować własne funkcje. Funkcja może być bezparametrowa. Oto przykład bezparametrowej funkcji, zwracającej zawsze liczbę całkowitą trzynaście: int F_Trzynascie() { return 13; } Poprawne wywołanie naszej funkcji w programie głównym miałoby postać: int main() { ...... int X; ........ // Funkcja typu int nie musi byc deklarowana. X = F_Trzynascie(); ...... } Jeśli funkcja musi pobrać jakieś parametry od programu (funkcji wyższego poziomu, wywołującej)? Zwróć uwagę, że program główny w C/C++ to też funkcja - main(). Przykład następny pokazuje definicję funkcji obliczającej piątą potęgę pobranego argumentu i wywołanie tej funkcji w programie głównym. Przykład: int F_XdoPiatej(int argument) { int robocza; //automatyczna wewnetrzna zmienna funkcji robocza = argument * argument; robocza = robocza * robocza * argument; return (robocza); } int main() { int Podstawa, Wynik, a, b; ... /* Funkcja nie jest deklarowana przed uzyciem */ Wynik = F_XdoPiatej(Podstawa); ..... a = F_XdoPiatej(b); ..... return 0; } Zwróć uwagę, że definiując funkcję podajemy nazwę i typ ARGUMENTU FORMALNEGO funkcji - tu: argument. W momencie wywołania na jego miejsce podstawiany jest rzeczywisty bieżący argument funkcji. Aby zapewnić wysoką dokładność obliczeń wymienione wyżej funkcje biblioteczne sqrt(), sin() itp. "uprawiają" arytmetykę na długich liczbach typu double. Funkcję taką przed użyciem w swoim programie MUSISZ ZADEKLAROWAĆ. Przykład: [P045.CPP] main() { double a, b; double sqrt(); // tu skasuj deklaracje funkcji sqrt() // a otrzymasz bledny wynik ! clrscr(); printf("Podaj liczbe\n"); scanf("%lf", &a); b = sqrt(a); printf("\n %Lf", (long double) b); getch(); return 0; } PROTOTYPY FUNKCJI, czyli jeszcze o deklaracjach funkcji. Prototyp funkcji to taka deklaracja, która: * została umieszczona na początku programu poza funkcją main(), * zawiera deklarację zarówno typu funkcji, jak i typów argumentów. Przykład prototypu (funkcja2.cpp): double FUNKCJA( double X, double Y); main() { double A=0, B=3.14; printf("Wynik działania funkcji: \n"); printf("%lf", FUNKCJA(A,B)); return 0; } double FUNKCJA(double X, double Y) { return ((1+X)*Y); } Prototyp mógłby równie dobrze wyglądać tak: double FUNKCJA(double, double); nazwy parametrów formalnych nie są istotne i można je pominąć. Jeśli prototyp funkcji wygląda tak: int Funkcja(int, char*, &float) oznacza to, że parametrami funkcji są wskaźniki do zmiennych, bądź referencje do zmiennych. Przy rozszyfrowywaniu takiej "abrakadabry" warto wiedzieć, że char* oraz char * int& oraz int & ma w tym przypadku identyczne znaczenie. W C++ wolno nie zwracać wartości funkcjom typu void. To dlatego właśnie często rozpoczynaliśmy programy od void main() Skutek praktyczny: Jeśli w ciele funkcji typu void występuje instrukcja return (nie musi wystąpić) to instrukcja ta nie może mieć argumentów. Oto przykład prototypu, definicji i wywołania funkcji typu void: [P046.CPP] #include #include void RYSUJPROSTOKAT( int Wys, int Szer, char Wzorek); void main() { clrscr(); RYSUJPROSTOKAT(5, 20, '€'); // klocek ASCII 176 - [Alt]-[176] getch(); RYSUJPROSTOKAT(15, 15, '€'); //[Alt]-[177] getch(); } void RYSUJPROSTOKAT( int Wys, int Szer, char Wzorek) { int i, j; // automatyczne zmienne wewnętrzne funkcji for(i=1; i<=Wys; i++) { for(j=1; j<=Szer; j++) printf("%c",Wzorek); printf("\n"); } } Prototypy wszystkich funkcji standardowych znajdują się w plikach nagłówkowych *.H (ang. Header file). Skutek praktyczny: JEŚLI DOŁĄCZYSZ DO PROGRAMU STOSOWNE PLIKI NAGŁÓWKOWE *.h,możesz ZREZYGNOWAĆ Z DEKLARACJI FUNKCJI. Dodając do programu wiersz: #include dołączający plik zawierający prototyp funkcji sqrt(), możesz napisać program tak: #include #include main() { double a, b; clrscr(); printf("Podaj liczbe\n"); scanf("%lf", &a); b = sqrt(a); printf("\n %Lf", (long double) b); getch(); return 0; } PRZEKAZYWANIE PARAMETRÓW DO FUNKCJI. W C++ często przekazuje się parametry do funkcji przy pomocy wskaźników. Aby prześledzić co dzieje się wewnątrz funkcji wpisz i uruchom podany niżej program przykładowy. Najpierw skonstruujemy sam program a następnie zmodyfikujemy go w taki sposób, abyś mógł sobie popodglądać cały proces. Przy pomocy funkcji printf() każemy wydrukować kolejne stany zmiennych, stan programu i funkcji, a funkcja getch() pozwoli Ci obejrzeć to "krok po kroku". Mogłoby się wydawać, że program poniżej skonstruowany jest poprawnie... void FUNKCJA( int ); //Prototyp, deklaracja funkcji void main() { int Zmienna; //Zmienna funkcji main, rzeczywisty argument clrscr(); Zmienna = 7; FUNKCJA( Zmienna); //Wywolanie funkcji printf("%d", Zmienna); //Wydruk wyniku } void FUNKCJA( int Argument) //Definicja funkcji { Argument = 10 * Argument + Argument; } FUNKCJA() jest jak widać trywialna. będzie zamieniać np. 2 na 22, 3 na 33 itp. tylko w tym celu, by łatwo było stwierdzić, czy funkcja zadziałała czy nie. Rozbudujmy program tak by prześledzić kolejne stadia. [P047.CPP] void FUNKCJA( int ); //Prototyp int Zmienna; void main() { clrscr(); printf("Stadium: \tZmienna Argument"); printf("\nStadium 1\t%d\tnie istnieje\n", Zmienna); Zmienna = 7; printf("Stadium 2\t%d\tnie istnieje\n", Zmienna ); FUNKCJA( Zmienna); printf("Stadium 3\t%d", Zmienna); // printf("%d", Argument); // taka proba sie NIE UDA ! getch(); } void FUNKCJA( int Argument) //Definicja funkcji { printf("jestesmy wewnatrz funkcji\n"); printf("Nastapilo kopiowanie Zmienna -> Argument\n" ); printf("\t\t%d\t%d\n", Zmienna, Argument); getch(); Argument = 10*Argument + Argument; printf("\t\t%d\t%d\n", Zmienna, Argument); getch(); } Próba wydrukowania zmiennej Argument gdziekolwiek poza wnętrzem FUNKCJI() nie uda się i spowoduje komunikat o błędzie. Oznacza to, że POZA FUNKCJĄ zmienna Argument NIE ISTNIEJE. Jest tworzona na stosie jako zmienna automatyczna na wyłączny użytek funkcji, w której została zadeklarowana i znika po wyjściu z funkcji. Przy takiej organizacji funkcji i programu funkcja otrzymuje kopię zmiennej, na niej wykonuje swoje działania, natomiast zmienna (zmienne) wewnętrzna funkcji znika po wyjściu z funkcji. Problem przekazania parametrów pomiędzy funkcjami wywołującymi ("wyższego rzędu" - tu: main) i wywoływanymi (tu: FUNKCJA) można rozwiązać przy pomocy * instrukcji return (zwrot do programu jednej wartości) lub * wskaźników. Możemy przecież funkcji przekazać nie samą zmienną, a wskaźnik do zmiennej (robiliśmy to już w przypadku funkcji scanf() - dlatego, że samej zmiennej jeszcze nie było - miała zostać dopiero pobrana, ale istniało już przeznaczone na tą nową zmienną - zarezerwowane dla niej miejsce. Mogł zatem istnieć wskaźnik wskazujący to miejsce). wskaźnik należy oczywiście zadeklarować. Nasz program przybrałby zatem nową postać. Wskaźnik do zmiennej nazwiemy *Argument. [P048.CPP] //Pamietaj o plikach naglowkowych ! void FUNKCJA( int *Argument); //Prototyp int Zmienna; void main() { clrscr(); printf("Stadium: \tZmienna Argument"); printf("\nStadium 1\t%d\tnie istnieje\n", Zmienna); Zmienna = 7; printf("Stadium 2\t%d\tnie istnieje\n", Zmienna ); FUNKCJA( &Zmienna); //Pobierz do funkcji ADRES Zmiennej printf("Stadium 3\t%d", Zmienna); // printf("%d", Argument); // taka proba sie NIE UDA ! getch(); } void FUNKCJA( int *Argument) // Definicja funkcji { printf("jestesmy wewnatrz funkcji\n"); printf("Nastapilo kopiowanie ADRESOW a nie zmiennej\n" ); printf("ADRESY:\t\t %X\t%X\n", &Zmienna, Argument); getch(); *Argument = 10* *Argument + *Argument; /* DZIALANIE */ printf("\t\t%d\t%d\n", Zmienna, *Argument); getch(); } W linii /* DZIALANIE */ mnożymy i dodajemy to, co wskazuje wskaźnik, czyli Zmienną. Funkcja działa zatem nie na własnej kopii zmiennej a bezpośrednio na zmiennej zewnętrznej. Zwróć uwagę na analogię w sposobie wywołania funkcji: FUNKCJA( &Zmienna ); scanf( "%d", &Zmienna ); A jeśli argumentem funkcji ma być tablica? Rozważ przykładowy program. Program zawiera pewną nadmiarowość (ku większej jasności mechanizmów). [P049.CPP] # include # include SUMA( int k, int Tablica[] ) { int i, SumTab=0; for (i=0; i10) { printf("TO ZA DUZO ! - max. 10"); continue; } suma = SUMA( N,TAB ); printf("\nTO JEST suma z progr. glownego %d", suma); printf("\n Jeszcze raz ? T/N"); Odp = getch(); } while (Odp!='N' && Odp!='n'); return 0; } Kompilacja w C++ jest wieloprzebiegowa (PASS 1, PASS 2), więc definicja funkcji może być zarówno na początku jak i na końcu. A oto następny przykład. Operując adresem - wskaźnikiem do obiektu (tu wskaźnikami do dwu tablic) funkcja Wypelniacz() zapisuje pod wskazany adres ciąg identycznych znaków. Na końcu każdego łańcucha znaków zostaje dodany NUL - (\0) jako znak końca. Taki format zapisu łańcuchów znakowych nazywa się ASCIIZ. [P050.CPP] void Wypelniacz(char *BUFOR, char Znak, int Dlugosc); char TAB2D[5][10]; // Tablica 5 X 10 = 50 elementow char TAB_1D[50]; // Tablica 1 X 50 = 50 elementow int k; main() { clrscr(); Wypelniacz( TAB_1D, 'X', 41); //Wypelnia X-ami printf("%s\n\n", TAB_1D); for (k=0; k<5; k++) Wypelniacz( TAB2D[k], 65+k, 9); //ASCII 65 to 'A'; 66 to 'B' itd. for (k=0; k<5; k++) printf("%s\n", TAB2D[k]); getch(); return 0; } void Wypelniacz( char *BUFOR, char Znak, int Dlugosc ) { int i; for ( i=0; i<=(Dlugosc-1); i++) *(BUFOR+i) = Znak; *(BUFOR+Dlugosc) = '\0'; } Zwróć uwagę, że: * NAZWA TABLICY (tu: TAB_1D i TAB2D) funkcjonuje jako wskaźnik PIERWSZEGO ELEMENTU TABLICY. FUNKCJE TYPU WSKAŹNIKOWEGO. Funkcje mogą zwracać do programu zarówno wartości typu int, czy float, jak i wartości typu ADRESU. Podobnie jak wskaźnik wymaga deklaracji i podania w deklaracji na jakiego typu obiekty będzie wskazywał, podobnie funkcja takiego typu wymaga w deklaracji określenia typu wskazywanych obiektów. Wiesz już, że zależy od tego tzw. krok wskaźnika. W przykładzie poniżej funkcja Minimum() poszukuje najmniejszego elementu tablicy i zwraca wskaźnik do tegoż elementu. Znając lokalizację najmniejszego elementu możemy utworzyć nową tablicę, ale już uporządkowaną według wielkości. [P051.CPP] int BALAGAN[10]; int PORZADEK[10]; // Tablica koncowa - uporzadkowana int k, *pointer , MAX=10000 ; int *Minimum(int Ilosc, int *TABL); main() { clrscr(); printf("Podaj 10 liczb calkowitych od -10000 do 10000\n"); for (k=0; k<=9; k++) scanf("%d", &BALAGAN[k]); printf("Po kolei: \n\n"); for ( k=0; k<=9; k++ ) { €€€€€pointer=Minimum(10, BALAGAN); €€€€€PORZADEK[k]=*pointer; €€€€€*pointer=MAX; } for(k=0; k<=9; k++) printf("%d ", PORZADEK[k]); getch(); return 0; } int *Minimum( int Ilosc, int *TABL ) { int *pMin; int i; pMin=TABL; for (i=1; i # include double NASZA( double ); //Deklaracja zwyklej funkcji double (*Funkcja)(double ARG); //pointer do funkcji double Liczba, Wynik; //Deklaracje zmiennych int WYBOR; main() { clrscr(); printf("Podaj Liczbe \n"); scanf("%lf", &Liczba); printf("CO MAM ZROBIC ?\n"); printf("1 - Sinus \n"); printf("2 - Pierwiastek\n"); printf("3 - Odwrotnosc 1/x\n"); scanf("%d", &WYBOR); switch(WYBOR) { case 1: Funkcja=sin; break; case 2: Funkcja=sqrt; break; case 3: Funkcja=NASZA; break; } Wynik=Funkcja(Liczba); // Wywolanie wybranej funkcji printf("\n\nWYNIK = %lf", Wynik); getch(); return 0; } double NASZA(double a) { printf("\n A TO NASZA PRYWATNA FUNKCJA\n"); if (a!=0) a=1/a; else printf("???\n"); return a; } main() - FUNKCJA SPECJALNA. Ta książka siłą rzeczy, ze względu na swoją skromną objętość i skalę zagadnienia o którym traktuje (autor jest zdania, że język C to cała filozofia nowoczesnej informatyki "w pigułce") pełna jest skrótów. Nie możemy jednak pozostawić bez, krótkiego choćby, opisu pomijanego dyskretnie do tej pory problemu PRZEKAZANIA PARAMETRÓW DO PROGRAMU. Konwencja funkcji w języku C/C++ wyraźnie rozgranicza dwa różne punkty widzenia. Funkcja pozwala na swego rodzaju separację świata wewnętrznego (lokalnego, własnego) funkcji od świata zewnętrznego. Nie zdziwi Cię więc zapewne, że i sposób widzenia parametrów przekazywanych programowi przez DOS i sposób widzenia "od wewnątrz" argumentów pobierabych przez funkcję main() jest diametralnie różny. To, co DOS widzi tak: PROGRAM PAR1 PAR2 PAR3 PAR4 PAR5 [...][Enter] funkcja main() widzi tak: main(int argc, char **argv, char **env) lub tak: main(int argc, char *argv[], char *env[]) [???]CO TO JEST ??? ________________________________________________________________ Zapisane zgodnie z obyczajami stosowanymi w prototypach funkcji: int argc - liczba całkowita (>=1, bo parametr Nr 1 to nazwa samego programu, za pośrednictwem której DOS wywołuje funkcję main). Liczba argumentów - parametrów może być zmienna. UWAGA: Język programowania wsadowego BPL przyjmuje nazwę programu za parametr %0 a C++ uznaje ją za parametr o numerze argv[0], tym niemniej, nawet jeśli nie ma żadnych parametrów argc = 1. argv - to tablica zawierająca wskaźniky do łańcuchów tekstowych reprezentowanych w kodzie ASCIIZ - nazw kolejnych paramentrów, z którymi został wywołany program. Pierszy element tej tablicy to nazwa programu. Ostatni element tej tablicy, o numerze argv - 1 to ostatni niezerowy parametr wywołania programu. env - to także tablica zawierająca wskaźniki do łańcuchów znakowych w kodzie ASCIIZ reprezentujących parametry środowiska (environment variables). Wskaźnik o wartości NUL sygnalizuje koniec tablicy. W Turbo C++ istnieje także predefiniowana zmienna globalna (::), przy pomocy której można uzyskać dostęp do środowiska operacyjnego - environ . ________________________________________________________________ Przykłady poniżej przedstawiają sposób wykorzystania parametrów wejściowych programu. [P053.CPP] # include "stdio.h" # include "stdlib.h" main(int argc, char *argv[], char *env[]) { printf("Parametry srodowiska DOS: \n"); int i = 0; do { printf("%s \n", env[i]); i++; }; while (env[i] != NULL); printf("Lista parametrow programu: \n"); for(i=1; i<= argc - 1; i++) printf("%s \n", argv[i]); printf("Nazwa programu: \n"); printf("%s", argv[0]); return 0; } Ponieważ C++ traktuje nazwę tablicy i wskaźnik do tablicy w specjalny sposób, następujące zapisy są równoważne: *argv[] oraz **argv *env[] oraz **env Nazwy argumentów argc, argv i env są zastrzeżone i muszą występować zawsze w tej samej kolejności. Argumenty nie muszą występować zawsze w komplecie. Dopuszczalne są zapisy: main(int argc, char **argv, char **env) main(int argc, char *argv[]) main(int argc) main() ale niedopuszczalny jest zapis: main(char *env[]) Nawet jeśli nie zamierzamy wykorzystać "wcześniejszych" parametrów - MUSIMY JE PODAĆ. [Z] ________________________________________________________________ 1. Spróbuj tak zmodyfikować funkcję Demo(), by liczba w formie dwójkowej była pisana "od tyłu". Do cofania kursora w funkcji printf użyj sekwencji \b\b. 2. Zinterpretuj zapis: if (MIANOWNIK) printf("%f", 1/MIANOWNIK); else exit(1); 3 Spróbuj przeprowadzić rzutowanie typu we własnym programie. 4 Przekaż wartość w programie przykładowym posługując się instrukcją: return (10*Argument + Argument); 5 Rozszerz zestaw funkcji do wyboru w programie przykładowym. ________________________________________________________________