[20:59] <@Gynvael>: Witam wszystkich na ostatnim wykladzie z Podstaw jezyka C ;>
[20:59] phoenix__: CZEMU OSTATNIM ?
[20:59] <@Gynvael>: phoenix__ csii ;>
[20:59] <@Gynvael>: Przez odstatnie 11 wykladow (+ dzisiaj to 12) pojawily sie podstawy jezyka C, glownie sklania
[20:59] <@Gynvael>: typy zmiennych, struktury, funkcje etc
[21:00] <@Gynvael>: Dlatego mam nadzieje ze osoby ktore w tych wykladach uczestniczyly (badz czytaly logi) znaja juz podstawy jezyka C ;>
[21:00] <@Gynvael>: Dzisiaj bedzie chwile o parserach, potem o pointerach do funkcji i na koniec o czestych bledach popelnianych przez programistow
[21:01] <@Gynvael>: Natomiast od nastepnego tygodnia w srody o 21
[21:01] <@Gynvael>: bedzie wyklad zatytulowany "Wykorzystanie jezyka C do tworzenia gier" ;>
[21:01] <@Gynvael>: czyli w sumie bardziej moja dzialka
[21:01] <@Gynvael>: Bedize to prawdopodobnie seria wykladow
[21:02] <@Gynvael>: Kazdy bedzie oddzielna caloscia na temat jednej gry
[21:02] <@Gynvael>: tudziez jednego rodzaju
[21:02] <@Gynvael>: W srode zaczniemy od C, libSDL + OpenGL i gry typu Sokoban (takie tam ukladanie skrzynek w magazynie)
[21:02] <@Gynvael>: co bedzie pozniej sie okaze ;>
[21:02] <@Gynvael>: OK
[21:02] <@Gynvael>: A
[21:03] <@Gynvael>: Jeszcze jedno ogloszenie parafialne
[21:03] <@Gynvael>: jako ze parenascie ostatnich godzin sajt wyklady.vexillium.org lezal, to terminarz bedzie updatniety dopiero pozniej
[21:03] <@Gynvael>: powiem tylko ze jutro jest wyklad z PHP (by Nekrataal)
[21:03] <@Gynvael>: w Sobote beda 3 wyklady
[21:04] <@Gynvael>: a w niedziele prawdopodobnie jeden
[21:04] <@Gynvael>: z tym ze dokladnie nie pamietam z czego
[21:04] <@Gynvael>: ;p
[21:04] <@Gynvael>: w terminarzu sie znajdzie
[21:04] <@Gynvael>: OK
[21:04] <@Gynvael>: tyle ogloszen parafialnych
[21:04] Blizzard: ;>
[21:04] <@Gynvael>: jakies pytania ?
[21:04] wSiwy: niee
[21:04] maxbog: bedzie jakis wyklad w piatek?
[21:04] Blizzard: Gynvael: anni juz php nie prowadzi?
[21:05] <@Gynvael>: aa w Piatek ofc standardowo Perl by mulander
[21:05] <@Gynvael>: Blizzard php jest prowadzone na zmiane przez Anniego i Neka
[21:05] <@Gynvael>: ;>
[21:05] Blizzard: Ok
[21:05] G0blin: ja mam
[21:05] Blizzard: Gynvael: a c++ bedzie?
[21:05] phoenix__: z czego beda wyklady w sobote
[21:05] Blizzard: czy samo c
[21:05] Blizzard: ;>
[21:05] G0blin: beda gry w lnxie?
[21:05] phoenix__: delphi , bash i ??
[21:05] maxbog: bedie cos o c# ?
[21:05] Evill: g0blin : pielegnacja fluxa
[21:05] maxbog: :)
[21:05] <@Gynvael>: Blizzard: bedzie kurs C++ PRAWDOPODOBNIE od za 2 tyg...
[21:06] Blizzard: ble! delphi ble
[21:06] <@Gynvael>: Blizzard: ja raczej o C bede mowil
[21:06] Blizzard: Gynvael: OO!
[21:06] Blizzard: a kto c++?
[21:06] Blizzard: i czym to sie roznic bedzie
[21:06] Evill: ale o grach tez moge zrobic bo emulowalem win 98 i cedege na linku :P
[21:06] Evill: ;]
[21:06] G0blin: Evill: nie o to pytalem
[21:06] <@Gynvael>: maxbog: ne.. o C# nic nie wiem.. ani nie bylo zainteresowania ze strony "studentow" ani ze strony wykladowcow
[21:06] defc0n: ja lece
[21:06] defc0n: narazie
[21:06] maxbog: buuu
[21:06] Evill: a to luz
[21:06] G0blin: Gynvael: bedzie o pisaniu gier w lnxie? :>
[21:06] <@Gynvael>: Blizzard: powiem kto jak bedzie sprawa jasna
[21:06] Blizzard: spoko
[21:06] Blizzard: tylko wydaje mi sie
[21:07] Blizzard: ze nie bedzie od poczatku
[21:07] <@Gynvael>: ;>
[21:07] Blizzard: tylko chyba uzupelnienie twoich i zmiana niektorych rzeczy
[21:07] <@Gynvael>: G0blin: postaram sie wyklad prowadzic "cross-platformowo" ;> czyli zeby i na windzie i na linie dzialalo
[21:07] G0blin: ok
[21:07] phoenix__: oo fajnie
[21:07] <@Gynvael>: Blizzard imho od podstaw ;>
[21:07] phoenix__: ja nie lubie win
[21:07] G0blin: i bedzie nowa klatwa?
[21:07] Blizzard: Gynvael: aha:D
[21:08] <@Gynvael>: ok
[21:08] <@Gynvael>: jeszcze jakies pytania ?
[21:08] <@Gynvael>: G0blin?
[21:08] G0blin: znaczy chodzi mi o to, czy beda tez omawiane biblioteki
[21:08] G0blin: dzialajace
[21:08] G0blin: tylko na jednej platformie
[21:08] G0blin: ?
[21:08] <@Gynvael>: G0blin: raczej ne
[21:08] G0blin: szkoda
[21:08] <@Gynvael>: G0blin: tzn nie przezemnie
[21:09] <@Gynvael>: G0blin: jesli ktos inny bedzie chcial to ofc ;>
[21:09] G0blin: izi
[21:09] <@Gynvael>: ok
[21:09] G0blin: gogogo
[21:09] G0blin: :]
[21:09] <@Gynvael>: jeszcze jakies pytanka ?
[21:09] maxbog: gogo
[21:09] phoenix__: Gynvael: co bedzie w sobote ?
[21:09] phoenix__: DELPHI BASH I ???
[21:09] maxbog: perl
[21:09] <@Gynvael>: phoenix__: ee bash w nidziele jest
[21:10] G0blin: szkoda czasu
[21:10] phoenix__: a w sobote ?
[21:10] <@Gynvael>: phoenix__: dephi, matma i bodajze cos o fluxboxie (instalacja + pielegnacja).. ale to dokladnei msuze looknac
[21:10] Evill: perl r0x ;)
[21:10] G0blin: zobaczycie na stronce sobie
[21:10] <@Gynvael>: ok
[21:10] <@Gynvael>: ok
[21:10] <@Gynvael>: go ?
[21:10] G0blin: go
[21:10] <@Gynvael>: ok
[21:10] <@Gynvael>: ;>
[21:10] <@Gynvael>: wiec
[21:10] <@Gynvael>: 3 slowa jeszzcze o parserkach ;>
[21:11] <@Gynvael>: ostatnio robilismy parsing, gdy mielismy dostep odrazu do wszystkich danych
[21:11] <@Gynvael>: np czytalismy z pliku po slowach etc
[21:11] <@Gynvael>: natomiast zdarzaja sie przypadki
[21:11] <@Gynvael>: kiedy nie dostajemy wszystkiego odrazu
[21:12] <@Gynvael>: dostajemy partiami ;>
[21:12] <@Gynvael>: np zalozmy ze dane maja 100 bajtow
[21:12] <@Gynvael>: jesli np sciagamy cos z sieci
[21:12] <@Gynvael>: to moze sie zdarzyc ze dostaniemy to na raty:
[21:12] <@Gynvael>: - 2 bajty
[21:12] <@Gynvael>: - 12 bajtow
[21:12] <@Gynvael>: - 50 bajtow
[21:12] <@Gynvael>: - 1 bajt
[21:12] <@Gynvael>: - 1 bajt
[21:12] <@Gynvael>: etc
[21:13] <@Gynvael>: najlepiej jest w tym wypadku buforowac dane
[21:13] <@Gynvael>: tj jesli wiemy ze ma byc 100 bajtow
[21:13] <@Gynvael>: to zaalokowac jakas tablice na 100 bajtow i ja zapelniac po kolei danymi
[21:13] <@Gynvael>: a gdy dostaniemy wszystko, wtedy parsowac
[21:13] <@Gynvael>: sprawa sie jednak komplikuje w momencie gdy nie znamy wielkosci sciaganych danych
[21:14] <@Gynvael>: albo sa one jakiejs nieludzkiej wielkosci
[21:14] <@Gynvael>: np 1gb..
[21:14] <@Gynvael>: zadko ktory komp pozwolic moze sobie na alokacje tablicy wielkosc 1gb na dane ;p
[21:14] <@Gynvael>: ew gdy nie znamy wielkosci
[21:14] <@Gynvael>: to powiedzmy zaalokujemy 1024 bajty
[21:14] <@Gynvael>: a przyjdzie 1060 bajtow danych... i seg fault...
[21:15] <@Gynvael>: no ok, zaalokujemy 2000 bajtow, przyjdzie 2200...
[21:15] <@Gynvael>: etc
[21:15] <@Gynvael>: rozwiazania moga byc nastepujace:
[21:15] <@Gynvael>: 1) jesli nie musi to byc mega szybkie, mozemy sobie pakiety dopisywac do jakiegos pliku
[21:16] <@Gynvael>: tzn zalozyc jakis asdf.xxx, i po kolei zapisywac tam
[21:16] <@Gynvael>: a gdy dowiemy sie ze jest koniec, to przeparsowac/zajac sie danymi
[21:16] <@Gynvael>: natomiast operacje na dysku nei sa najszybsze
[21:17] <@Gynvael>: 2) jesli jednak zalezy nam na predkosci, mozemy zrobic sobie jakis modulik ktory bedzie umozliwial dynamiczne zwiekszanie jakiejs struktury danych, tak zebysmy mogli tam wrzucac dane nie martwiac sie ze mamy za mala tablice
[21:17] <@Gynvael>: (patrz modulik DSDB z mojego serverka www (http://gynvael.lunarii.org/temp/gosu.zip))
[21:18] <@Gynvael>: natomiast problem sie pojawia jesli faktycznie dostaniemy 1gb
[21:18] <@Gynvael>: 3) mozemy parsowac real-time, bez buforowania, np korzystajac ze Skonczonych Automatow Stanow (finite automata, finite state automata)
[21:19] <@Gynvael>: jest to w sumie nazwa na hmm, powiedzial bym sposob projektowania i zapisu pewnych algorytmow
[21:19] <@Gynvael>: ktory bardzo milo nadaje sie wlasnie do parserow
[21:19] <@Gynvael>: http://www.gynvael.vexillium.org/stuff/http_parse_diag.gif <=- przykladowy automat stanow
[21:20] <@Gynvael>: automaty sie mniej wiecej tak ilustruje graficznie
[21:20] <@Gynvael>: nie bede sie o nich rozwodzil, mozna poczytac
[21:20] <@Gynvael>: ogolnei chodzi o stworzenie kilku-kilkunastu "stanow" w ktorych moze byc parser
[21:21] <@Gynvael>: przykladowo dla plikow ini o ktorych mowilismy
[21:21] <@Gynvael>: czyli:
[21:21] <@Gynvael>: [ala]
[21:21] <@Gynvael>: ala=kot
[21:21] <@Gynvael>: mozna by wyznaczyc takie stany:
[21:22] <@Gynvael>: poczatek: przed analiza... tutaj moze pojawic sie: SPACJA (wtedy nie zmieniamy stanu), znak [ (wtedy zmieniamy stan na "nazwa_sekcji"), badz jakas literka (wtedy zmieniamy stan na "nazwa_pola")
[21:22] <@Gynvael>: jesli by pojawil sie jakis inny znak, to oznacza ze jest blad ;> przerywamy i zglaszamy blad
[21:23] <@Gynvael>: nazwa_sekcji: tutaj moze sie pojawic: literka - wtedy ja zapamietujemy (np dopisujemy do jakiegos stringa), i nei zmieniamy stanu, badz znak ] (wtedy idziemy do stanu "koniec")
[21:24] <@Gynvael>: nazwa_pola: jesli pojawi sie literka, to zapamietujemy i nie zmieniamy stanu, jesli znak =, to zmieniamy stan na "wartosc_pola"
[21:24] <@Gynvael>: wartosc_pola: jesli pojawi sie znak konca lini badz \0, idziemy do "koniec", w innym wypadku zapamietujemy wartosc
[21:24] <@Gynvael>: koniec: koniec ;>
[21:25] <@Gynvael>: http://www.gynvael.vexillium.org/?stuff=http_parse.stuff
[21:25] <@Gynvael>: tam mozna poczytac o tego typu parserze zrobionym do zapytan HTTP
[21:25] <@Gynvael>: sa tam rowniez dwa przyklady implementacji
[21:26] <@Gynvael>: oraz wytlumaczenie jak co dziala
[21:26] <@Gynvael>: ;>
[21:26] <@Gynvael>: ok
[21:26] <@Gynvael>: pytanka do tego ? w sumie poczytajcie tam i na necie o tym ;> warto
[21:27] Mijagi: gyn chcesz zostac nauczycielem informatyki? ;>
[21:27] phoenix__: po co to tzn do czego sie tego uzywa ?
[21:27] <@Gynvael>: Mijagi ;p
[21:27] Mijagi: ^^
[21:27] phoenix__: GynAway: to dobry pomysl
[21:27] <@Gynvael>: phoenix__: jesli nie mozna buforowac danych ;>
[21:27] sulfur: Mijagi: tak zle mu zyczysz?
[21:27] Mijagi: wtedy bedzie wiecej gosu informatykow w polsce ;)
[21:27] phoenix__: Mijagi: wtedy bedzie gosu programingu informatykow
[21:27] Mijagi: sulfur czemu zle? ;>
[21:28] <@Gynvael>: phoenix__: ew normalnie mozna uzywac, ten sposob jest porownywanie szybki do innych rodzajow parserow
[21:28] <@Gynvael>: ;>
[21:28] Mijagi: =)
[21:28] phoenix__: Gynvael: aha
[21:28] sulfur: Mijagi: taki potencjal chcesz w szkole zamknac i zmarnowac ?
[21:28] sulfur: wstydz sie
[21:28] G0blin: Gynvael: nie zostawaj nauczycielem infy
[21:28] <@Gynvael>: ;p
[21:28] G0blin: nie marnuj sie tak
[21:28] <@Gynvael>: ok
[21:28] phoenix__: Gynvael: czemuy masz 2 sesje ?
[21:28] <@Gynvael>: jakies pytanka na temat ?
[21:28] G0blin: chybe, ze wykladowca na uczelni
[21:28] G0blin: to co innego :P
[21:28] <@Gynvael>: phoenix__: bo z shella mam laga ;p
[21:28] Mijagi: sulfur Gyn=>20dobrych pokolen + niezla praca naukowa ;P
[21:28] Mijagi: imho
[21:28] phoenix__: Gynvael: ale ja musze 2 razy tab naciskac ;.
[21:29] phoenix__: ;/
[21:29] Mijagi: =)
[21:29] sulfur: zdajesz sobie sprawe jak gynv moze zmienic swiat i informatyke w przyszlosci ?
[21:29] <@Gynvael>: pasuje ?;p
[21:29] phoenix__: ooo
[21:29] phoenix__: pasi
[21:29] Mijagi: jasne ;)
[21:29] <@Gynvael>: ok
[21:29] <@Gynvael>: cos jeszcze ?
[21:29] phoenix__: teraz mi goblin przeszkadza ;PPPPPP
[21:29] phoenix__: no ale nvm
[21:29] d0b0c0p: duzo sie spozilem? ;p
[21:29] phoenix__: d0b0c0p: nie
[21:29] Mijagi: zdziebko ;>
[21:29] phoenix__: d0b0c0p: o parasingu glownie bylo
[21:29] Mijagi: trudne przegapiles ;P
[21:30] phoenix__: d0b0c0p: takie pierdoly
[21:30] d0b0c0p: ;pp
[21:30] G0blin: dzuiala :P
[21:30] Mijagi: ^^ g0blin uoperator
[21:30] d0b0c0p: jedziemy dalej? ;p
[21:30] phoenix__: G0blin: plz
[21:30] <@Gynvael>: ;p
[21:30] <@Gynvael>: lol
[21:31] phoenix__: G0blin: zmien nick na ag0blin
[21:31] phoenix__: albo cos takiego
[21:31] <@Gynvael>: ehehe
[21:31] <@Gynvael>: ok
[21:31] <@Gynvael>: lecimy dalej
[21:31] <@Gynvael>: tyle o parserach ;>
[21:31] <@Gynvael>: teraz o czyms o czym zapomnialem w sumie
[21:31] <@Gynvael>: mianowicie wskazniki na funkcje
[21:31] <@Gynvael>: jak kazdy wie, a ci co bawia sie assemblerem to wiedza nawet o tym bardziej
[21:31] <@Gynvael>: funkcja to po prostu blok kodu
[21:31] <@Gynvael>: blok kodu ktory ma swoj poczatek i koniec ;>
[21:32] <@Gynvael>: a jesli ma poczatek, to musi miec tez adres
[21:32] <@Gynvael>: co nam daje to ze funkcja ma adres ?
[21:32] <@Gynvael>: mniej wiecej tyle ze nie trzeba wcale odwolywac sie niej poprzez nazwe
[21:32] <@Gynvael>: mozemy przez adres do niej
[21:32] <@Gynvael>: http://gynvael.lunarii.org/temp/func_001.c
[21:33] <@Gynvael>: rzuccie okiem na ten program
[21:34] <@Gynvael>: ok
[21:34] <@Gynvael>: co tam jest?
[21:34] <@Gynvael>: 1) funkcja asdf
[21:34] <@Gynvael>: prosta ne ?
[21:34] <@Gynvael>: 2) main w ktorym jest nastepujaca deklaracja
[21:34] <@Gynvael>: void (*pointer_do_funkcji)(void);
[21:34] <@Gynvael>: zaraz powiem jak sie cos tkaiego tworzy
[21:34] <@Gynvael>: narazie uwierzcie mi na slowo ze jest to pointer do funkcji
[21:35] <@Gynvael>: funkcji o prototypie void nazwa(void)
[21:35] <@Gynvael>: nastepnie
[21:35] <@Gynvael>: pointer_do_funkcji = asdf;
[21:35] <@Gynvael>: robimy cos takiego
[21:35] <@Gynvael>: asdf to nasza funkcja
[21:35] <@Gynvael>: asdf() to jej wywolanie
[21:35] <@Gynvael>: a samo asdf to jej adres (tak jak jest z tablicami.. nazwa == adres)
[21:36] <@Gynvael>: czyli poiter_do_funkcji po tej operacji ma adres funkcji asdf
[21:36] <@Gynvael>: nastepnie jest wywolanie asdf
[21:36] <@Gynvael>: oraz wywolanie funkcji KTOREJ ADRES ZAWIERA pointer_do_funkcji
[21:36] <@Gynvael>: teraz po kolei, ale dokladniej
[21:36] <@Gynvael>: void (*pointer_do_funkcji)(void);
[21:37] <@Gynvael>: pointer_do_funkcji to ofc nazwa zmiennej ;>
[21:37] <@Gynvael>: int a; <=- a to tez nazwa zmiennej
[21:37] <@Gynvael>: i teraz podam taki "szczwany" sposob tworzenia pointerow
[21:37] <@Gynvael>: zalozmy ze chcemy utworzyc pointer do funkcji typu
[21:37] <@Gynvael>: int nazwa(int a, char *b);
[21:37] <@Gynvael>: robimy tak
[21:38] <@Gynvael>: piszemy to sobie w deklaracjach, zamiast nazwa dajemy nazwe zmiennej jaka chcemy
[21:38] <@Gynvael>: int pointer(int a, char *b);
[21:38] <@Gynvael>: po czym wrzucamy nazwe w nawias
[21:38] <@Gynvael>: int (pointer)(int a, char *b);
[21:38] <@Gynvael>: i przed nia dajemy *
[21:38] <@Gynvael>: int (*pointer)(int a, char *b);
[21:38] <@Gynvael>: (w nawiasie)
[21:38] <@Gynvael>: i juz mamy pointer do funkcji o danym typie
[21:39] <@Gynvael>: teraz tak
[21:39] <@Gynvael>: NAZWY ARGUMENTOW FUNKCJI W DEKLARACJI POINTERA DO FUNKCJI SA BEZ ZNACZENIA
[21:39] <@Gynvael>: mozemy napisac:
[21:39] <@Gynvael>: int (*pointer)(int a, char *b);
[21:39] <@Gynvael>: int (*pointer)(int, char*);
[21:39] <@Gynvael>: int (*pointer)(int ala, char* makota);
[21:39] <@Gynvael>: to bez znaczenia
[21:39] <@Gynvael>: raczej nazw wogole sie nie daje
[21:40] <@Gynvael>: ok
[21:40] <@Gynvael>: lecimy dalej
[21:40] <@Gynvael>: pointer_do_funkcji = asdf;
[21:40] <@Gynvael>: jak mowilem nazwa funkcji jest jej adresem
[21:40] <@Gynvael>: ale tutaj mozna zrobic cos co poczatkujacych programistow (a czesem i tych niepoczatkujacych) wyprowadza bardzo w pole
[21:40] <@Gynvael>: ;p
[21:40] <@Gynvael>: mianowicie
[21:40] <@Gynvael>: C BEZ PROBLEMU PRZYJMNIE ROWNIEZ NASTEPUJACE ZAPISY (ktore sa rownowazne temu):
[21:40] <@Gynvael>: pointer_do_funkcji = &asdf;
[21:40] <@Gynvael>: pointer_do_funkcji = *asdf;
[21:40] <@Gynvael>: pointer_do_funkcji = **asdf;
[21:40] <@Gynvael>: pointer_do_funkcji = ***********************************asdf;
[21:40] <@Gynvael>: ;>
[21:41] <@Gynvael>: (natomaist nie przyjmie &&&&&&&&asdf poniewaz kompilator ma polityke "wez najwiecej ile zdolasz" i &&&&& traktuje jako polaczenia znakow && && && etc ;> czyli and logiczne ;p)
[21:42] <@Gynvael>: mozna dac jedno &asdf
[21:42] <@Gynvael>: mozna dac asdf
[21:42] <@Gynvael>: mozna dac *asdf
[21:42] <@Gynvael>: w przypadku FUNKCJI to BEZ ROZNICY
[21:42] <@Gynvael>: kazdy z tych sposobow zwroci to samo, czyli adres funkcji
[21:42] <@Gynvael>: pointer_do_funkcji();
[21:42] <@Gynvael>: to jest wyowalanie
[21:43] <@Gynvael>: czyli korzystamy z tego normalnei jak z funkcji
[21:43] <@Gynvael>: zadnych udziwnien
[21:43] <@Gynvael>: zadnych * nie trzeba dawac
[21:43] <@Gynvael>: etc
[21:43] <@Gynvael>: ok
[21:43] <@Gynvael>: teraz przejdzmy do jakiegos konkretnego zastosowana
[21:43] <@Gynvael>: *zastosowania
[21:43] <@Gynvael>: narazie prosty, raczej bezsensowny przyklad ;>
[21:44] <@Gynvael>: http://gynvael.lunarii.org/temp/func_002.c
[21:44] <@Gynvael>: ogolnie jest to program ktory pyta usera o jakies baaaaaardzo proste rownanie
[21:44] <@Gynvael>: np 1+2
[21:44] <@Gynvael>: albo 4-3
[21:44] <@Gynvael>: (obsluguje tylko + i -)
[21:44] <@Gynvael>: i zwraca wynik
[21:45] <@Gynvael>: mamy tam dwie funkcje o identycznym prototypie
[21:45] <@Gynvael>: czyli dodaj i odejmij
[21:45] <@Gynvael>: prototyp ich to: int nazwa(int,int)
[21:45] <@Gynvael>: ;>
[21:45] <@Gynvael>: nastepnie mamy w main pare deklaracji
[21:45] <@Gynvael>: char dzialanie;
[21:45] <@Gynvael>: int a, b;
[21:45] <@Gynvael>: int (*funkcja)(int, int) = NULL;
[21:45] <@Gynvael>: jak widac funkcja jest pointerem na funkcje o podobnym prototypie co dodaj i odejmij
[21:46] <@Gynvael>: NULL to ofc adres 0 ;>
[21:46] <@Gynvael>: potem mamy jakiegos tam scanf
[21:46] <@Gynvael>: scanf("%i%c%i", &a, &dzialanie, &b);
[21:46] <@Gynvael>: ktory pobiera dwa inty i chara
[21:46] <@Gynvael>: a nastepnie takiego ifa
[21:46] <@Gynvael>: if(dzialanie=='+') funkcja = dodaj;
[21:46] <@Gynvael>: else if(dzialanie=='-') funkcja = odejmij;
[21:46] <@Gynvael>: ktory w zaleznosci od tego co dostanie, wrzuca do "funkcja" adres odpowiedniej funkcji ;> (odejmowania badz dodawania)
[21:47] <@Gynvael>: lub nie zmienia wartosci "funkcja"
[21:47] <@Gynvael>: potem jest kolejny if
[21:47] <@Gynvael>: if(funkcja) printf("wynik: %i\n", funkcja(a,b));
[21:47] <@Gynvael>: jak pamietacie if(funckja) to skrocony zapis if(funkcja != NULL)
[21:47] <@Gynvael>: czyli jesli jest jakas funkcja, to odpala ja z parametrami a i b, i wypisuje wynik
[21:48] <@Gynvael>: 21:49:39 LiTeStEp >func_002
[21:48] <@Gynvael>: 3+4
[21:48] <@Gynvael>: wynik: 7
[21:48] <@Gynvael>: u mnei dziala ;>
[21:48] <@Gynvael>: ok
[21:48] <@Gynvael>: pytania do tego ?
[21:48] <@Gynvael>: zaraz ciag dalszy
[21:48] Mijagi: od kiedy masz D+>
[21:48] Mijagi: ?
[21:48] Mijagi: ;>
[21:48] <@Gynvael>: Mijagi od kawalka czasu --; za dlugiego --; bija mnie tak ze z tego wyjsc nie moge --;
[21:49] Mijagi: =)
[21:49] Mijagi: goblin[21:49] Mijagi: po kursie 1v1?
[21:49] <@Gynvael>: a jakies pytanka na temat ?
[21:49] <@Gynvael>: zobaczymy
[21:49] <@Gynvael>: ;p
[21:49] Mijagi: ^^
[21:49] Mijagi: ide stad
[21:49] Mijagi: bo nic nie kminie :p
[21:50] G0blin: chyba zes na leb upadl
[21:51] <@Gynvael>: ;p
[21:51] G0blin: dziala :]
[21:51] <@Gynvael>: ok
[21:51] <@Gynvael>: lecimy dalej
[21:51] G0blin: σσσσσσσ
[21:51] G0blin: :]
[21:51] <@Gynvael>: ok
[21:51] <@Gynvael>: teraz przyklad troche bardziej z zycia wziety
[21:52] <@Gynvael>: http://gynvael.lunarii.org/temp/func_003.c
[21:52] <@Gynvael>: ten sam program, z paroma zmianami
[21:52] <@Gynvael>: 1) doszla funkcja pomnoz
[21:52] <@Gynvael>: 2) char dzialanie zmienilem na unsigned char dzialanie
[21:52] <@Gynvael>: typedef int (*ptr)(int, int);
[21:52] <@Gynvael>: doszlo cos takiego
[21:53] <@Gynvael>: nie bede przypominal jak dziala typedef ;>
[21:53] <@Gynvael>: powiem tylko ze tworzy nowy typ rownoznaczny podanemu typowi ;p
[21:53] <@Gynvael>: static ptr funkcje[256];
[21:53] <@Gynvael>: to jest utworzenie statycznej tablicy pointerow na funkcje ;p
[21:53] <@Gynvael>: o static chyba juz mowilem
[21:54] <@Gynvael>: na wszelki wypadek sie powtorze
[21:54] <@Gynvael>: static uzywa sie z dwoch powodow
[21:54] <@Gynvael>: 1) do zmiennych globalnych i funkcji, zeby byly widoczne TYLKO W DANYM OBIEKCIE (tj nie zasmiecaly przestrzeni nazw ;>)
[21:55] <@Gynvael>: 2) przy zmiennych lokalnych, zeby te zmienne w sumie byly jednak globalne, tzn mniej wiecej tyle ze wartosc tej zmiennej miedzy kolejnymi wywolaniami funkcji sie nie zmieni poniewaz zmienna ta ma swoje miejsce (a nie jest tworzona przy wywolaniu funkcji) w pamieci zmiennych globalncyh i danych
[21:56] <@Gynvael>: implikacja tego ostatniego jest to ze ta zmienna jest wyzerowana na poczatku ;> (zmienne lokalne NIE SA ZEROWANE)
[21:56] <@Gynvael>: (a globalne tak)
[21:56] <@Gynvael>: ok
[21:56] <@Gynvael>: glownie static po to uzylem zeby ta tablica byla wyzerowana
[21:56] <@Gynvael>: czyli kazdy jej element wynosil NULL
[21:56] <@Gynvael>: funkcje['+'] = dodaj;
[21:56] <@Gynvael>: funkcje['-'] = odejmij;
[21:56] <@Gynvael>: funkcje['*'] = pomnoz;
[21:56] <@Gynvael>: nastapnie mamy cos takiego
[21:56] <@Gynvael>: 'znak' to ofc kod ascii danego znaku
[21:56] phoenix__: idem pa gyn wyslij mi logi na maila jutro wszysytko powstawiam
[21:57] <@Gynvael>: kody ascii tychze znakow to 43, 45 i 42
[21:57] <@Gynvael>: phoenix__: kk
[21:57] <@Gynvael>: wiec spokojnie mozna by napisac
[21:57] <@Gynvael>: funkcje[43] = dodaj; etc
[21:57] <@Gynvael>: ale tak jest czytelniej (tzn z tymi '+')
[21:57] <@Gynvael>: czyli po tym cala tablica oprocz tych paru miejsc wskazuje na NULL
[21:57] <@Gynvael>: scanf("%i%c%i", &a, &dzialanie, &b);
[21:57] <@Gynvael>: potem jest znany nam scanf
[21:58] <@Gynvael>: a potem NIE MA TYCH IFOW ;>
[21:58] <@Gynvael>: if(funkcje[dzialanie])
[21:58] <@Gynvael>: printf("wynik: %i\n", funkcje[dzialanie](a,b));
[21:58] <@Gynvael>: ale mamy cos tkaiego
[21:58] <@Gynvael>: dzialanie to unsigned char
[21:58] <@Gynvael>: czyli zmienna z zakresu 0-255
[21:58] <@Gynvael>: funkcje to tablica z indexami od 0 do 255
[21:58] <@Gynvael>: zalozmy ze scanf do dzialania wczytal '+', czyli 43,
[21:59] <@Gynvael>: wtedy sprawdzamy
[21:59] <@Gynvael>: czy w funkcje['+'] jest cos..
[21:59] <@Gynvael>: jest.. adres funkcji dodaj
[21:59] <@Gynvael>: wiec ja wywolujemy
[21:59] <@Gynvael>: funkcje[dzialanie](a,b))
[21:59] <@Gynvael>: ;>
[21:59] <@Gynvael>: funkcje[dzialanie](a,b)
[21:59] <@Gynvael>: ;>
[21:59] <@Gynvael>: dzieki temu nei ma ifa
[21:59] <@Gynvael>: i wszystko chodzi szybciej etc
[22:00] <@Gynvael>: robienie takich tablic funkcji czasem jest dobrym pomyslem
[22:00] <@Gynvael>: dodam tylko ze NIE WARTO ZASTEPYWAC switch/case TAKIM CZYMS
[22:00] <@Gynvael>: powniewaz switch/case jest SZYBSZE i dziala na PRAWIE ZE TEJ SAMEJ ZASADZIE ;>
[22:01] <@Gynvael>: (o zasadzie dzialania switch/case mozna troche przeczytac tam -> http://www.gynvael.vexillium.org/?stuff=mit_elseif.stuff )
[22:01] <@Gynvael>: ok
[22:01] <@Gynvael>: a teraz jeszcze jedno zastosowanie pointerow do funkcji
[22:01] <@Gynvael>: ktore jest uzyte na przyklad..
[22:02] <@Gynvael>: w servisach na polnecie ;>
[22:02] <@Gynvael>: wiecie.. chanserv, nickserv etc ;>
[22:02] <@Gynvael>: z tym ze jako przykladem posluze sie prostym botem ircowym
[22:02] <@Gynvael>: http://www.gynvael.vexillium.org/?stuff=ircbot.stuff
[22:02] <@Gynvael>: zwroccie uwage tam na pare rzeczy:
[22:03] <@Gynvael>: typedef struct handle_proc_st { const char *name; int (*func)( int, const char *, const char *, char * ); } handle_proc_t;
[22:03] <@Gynvael>: hmmm
[22:03] <@Gynvael>: typedef struct handle_proc_st
[22:03] <@Gynvael>: [
[22:03] <@Gynvael>: {
[22:03] <@Gynvael>: const char *name;
[22:03] <@Gynvael>: int (*func)( int, const char *, const char *, char * );
[22:03] <@Gynvael>: } handle_proc_t;
[22:03] <@Gynvael>: czyli jest to struktura w ktorej jest string i jakis pointer do funkcji
[22:03] <@Gynvael>: troszke nizej mozna dojrzec tablice tych struykturek
[22:03] <@Gynvael>: handle_proc_t handles[ ] =
[22:04] <@Gynvael>: {
[22:04] <@Gynvael>: { "PING", handle_ping },
[22:04] <@Gynvael>: { "PRIVMSG", handle_msg },
[22:04] <@Gynvael>: { "JOIN", handle_join },
[22:04] <@Gynvael>: { "NICK", handle_nick },
[22:04] <@Gynvael>: { NULL, NULL }
[22:04] <@Gynvael>: };
[22:04] <@Gynvael>: PING, JOIN, NICK etc to sa polecenia/oznaczenia ktore wysyla server irca do klienta
[22:04] <@Gynvael>: a te funkcje, to funkcje obslugujace
[22:04] <@Gynvael>: dzieki czemus takiemu zamiast robic serie ifow do sprawdzenia jakie polecenie przyszlo
[22:05] <@Gynvael>: mozna zrobic:
[22:05] <@Gynvael>: for( iter = handles; iter->name && iter->func; iter++ )
[22:05] <@Gynvael>: {
[22:05] <@Gynvael>: if( strcmp( iter->name, type ) == 0 )
[22:05] <@Gynvael>: {
[22:05] <@Gynvael>: iter->func( sock, sender, type, p );
[22:05] <@Gynvael>: break;
[22:05] <@Gynvael>: }
[22:05] <@Gynvael>: }
[22:05] <@Gynvael>: czyli w petli sprawdzanie co przyszlo (strcmp) i jak sie znajdzie to wywolanie funkcji ktora jest za to odpowiedzialna
[22:06] <@Gynvael>: identyczne rozwiazanie jest w ircowych servisach ;>
[22:06] <@Gynvael>: oczywiscie sposob ten nie jest szybszy pod wzgledem dzialania od ifow
[22:06] <@Gynvael>: natomiast jest bardziej przejzysty
[22:06] <@Gynvael>: i wymaga mniej kodu
[22:06] <@Gynvael>: przez co latwiej wprowadzac zmiany
[22:07] <@Gynvael>: (szybsze bylo by szukanei funkcji obslugujacej w drzewku binarnym albo hashliscie, ale to dzialka g0blina ;p)
[22:07] <@Gynvael>: ok
[22:07] <@Gynvael>: jeszcze dwa zastosowania pointerow
[22:07] <@Gynvael>: w sumie podobne
[22:08] <@Gynvael>: w pierwszym przypadku rzuccie okiem na funkcjie qsort ze standardowego libc
[22:08] <@Gynvael>: void qsort(void *base, size_t nmemb, size_t size,
[22:08] <@Gynvael>: int (*compar)(const void *, const void *));
[22:08] <@Gynvael>: jest t ofunkcja sortujaca dowolne dane w tablicy
[22:08] <@Gynvael>: i jako ostatni parametr pobiera pointer do funkcji porownujacej dwa elementy w tablicy
[22:09] <@Gynvael>: dzieki czemu wystarczy zrobic inna funkcje porownnujacac zeby byly sortowane inty
[22:09] <@Gynvael>: inna zeby stringi
[22:09] <@Gynvael>: etc
[22:09] <@Gynvael>: nie trzeba calego sortowania pisac oddzielnei dla roznych typow danych
[22:09] <@Gynvael>: drugim przypadkiem jest zastosowanie podobne do atexit() z libc
[22:09] <@Gynvael>: int atexit(void (*function)(void));
[22:10] <@Gynvael>: ta funkcja pobiera pointer do funkcji ktora ma byc wykonana w jakims okreslonym wypadku, w tym przypadku jest to zakonczenie programu
[22:10] <@Gynvael>: (czy to poprzez exit() czy to poprzez return z maina)
[22:11] <@Gynvael>: pointerow do funkcji w ten sposob mozna uzyc np w kolejkach, listach laczonych
[22:11] <@Gynvael>: do automatycznego usuwania elementow (np user podaje funkcje uwalniajaca (np free), i przy usuwaniu elementu z listy jest on usuwany)
[22:11] <@Gynvael>: ok
[22:11] <@Gynvael>: type o pointerach do funkcji
[22:11] <@Gynvael>: pytanka ?
[22:11] G0blin: Gynvael: ja mialem
[22:12] G0blin: zaraz zobacze, bo zaznaczylem
[22:12] G0blin: juz wiem
[22:12] G0blin: mowiles o tym zerowaniu funkcji
[22:12] G0blin: zle
[22:12] G0blin: mowiles o tym zerowaniu zmiennych
[22:12] <@Gynvael>: (na marginesie dodam ze adres funkcji mozna uzyc rowniez do stworzenia SME - Self Modyfing Executalbe - ale to wyzsza szkola jazdy i sie na wyklad o podstawach C nie nadaje ;p)
[22:13] <@Gynvael>: tak ?
[22:13] G0blin: czy to jest tez dla innych jezykow?
[22:13] G0blin: (f.e. pascal)
[22:13] <@Gynvael>: uf
[22:13] <@Gynvael>: to zes dowalil
[22:13] <@Gynvael>: nie mam pojecia
[22:13] <@Gynvael>: ;>
[22:14] G0blin: ok
[22:14] <@Gynvael>: hehe
[22:14] G0blin: bo w pascalu z tego co wiem
[22:14] G0blin: sie deklaruje zmienne na samym poczatku
[22:14] G0blin: sa globalne
[22:14] G0blin: i zerowane
[22:14] G0blin: i tak mnie udezylo, czy to nie ta metoda
[22:14] <@Gynvael>: jako ciekawostke podam ze niektore kompilatory C w trybie debug ustawiaja zmeinne lokalne na wartosci skladajace sie z 0xC.. np 0xCCCCCCCC ;>
[22:15] G0blin: :]
[22:15] <@Gynvael>: ok
[22:15] <@Gynvael>: jeszcze jakies pytanka ?
[22:15] G0blin: ja mialem jeszcze uwage
[22:15] G0blin: :]
[22:15] G0blin: '(szybsze bylo by szukanei funkcji obslugujacej w drzewku binarnym albo hashliscie, ale to dzialka g0blina ;p)'
[22:16] G0blin: juz sie nie bede czepial malej literki
[22:16] G0blin: ale sie czepne tego
[22:16] G0blin: ze jak na moje wyklady nie beda przychodzili zadni programisci to po prostu do tego nie dojde :P
[22:16] G0blin: i chyba zaprzestane.....
[22:16] <@Gynvael>: ;p
[22:16] G0blin: bo to sie raczej mija z celem
[22:17] G0blin: ok, wszyscy uslyszeli
[22:17] G0blin: σσσσσσσσσσσσσσσ
[22:17] G0blin: :P
[22:17] <@Gynvael>: zrob jeszcze pare wykladow, moze sie rozkreci
[22:17] <@Gynvael>: ;>
[22:17] <@Gynvael>: a widzialem ze fajne byly ;>
[22:17] <@Gynvael>: ok
[22:17] <@Gynvael>: ok
[22:17] <@Gynvael>: jeszcze pare slow prze typowymi bledami
[22:18] <@Gynvael>: na temat roznych innych rzeczy typu static
[22:18] <@Gynvael>: czyli modyfikatorow zachowania kompilatora dot zmiennej badz funkcji;>
[22:19] <@Gynvael>: wiec
[22:19] <@Gynvael>: static znacie ;>
[22:19] <@Gynvael>: inline <=- to dajemy przed deklaracja funkcji i to zmusza kompilator zeby funkcja byla "wklejana" w miejce uzycia
[22:20] <@Gynvael>: czyli zamiast wywolania funkcji w skompilowanym kodzie zastaniemy kod tej funkcji w tamtym miejscu
[22:20] <@Gynvael>: wada jest zwiekszenie wielkosci kodu
[22:20] <@Gynvael>: ale zaleta jest zwiekszona wydajnosc
[22:20] <@Gynvael>: WARTO dawac inline przed MALE FUNKCJE KTORE SA BAAARDZO CZESTO UZYWANE
[22:21] <@Gynvael>: np jakies funkcje hashujace czy cos;>
[22:21] <@Gynvael>: volatile <=- to dajemy przed funkcja badz deklaracja zmiennej
[22:22] <@Gynvael>: jest to w sumie metoda powiedzenia kompilatorowi "NIE ZBLIZAJ SIE DO TEGO KODU/ZMIENNEJ ZE SWOIMI BRUDNYMI LAPSKAMI! PRZETLUMACZ TAK JAK JEST! NIC NIE ZMIENIAJ!"
[22:22] <@Gynvael>: ofc to znaczy ze kompilator zawsze proboje cos zmieniac ;>
[22:22] <@Gynvael>: bo tak jest, szczegolnie jak kompilujemy z optymalizacja
[22:22] <@Gynvael>: przykladowo
[22:22] <@Gynvael>: int x = 10;
[22:22] <@Gynvael>: printf("%i\n", x);
[22:22] <@Gynvael>: jak skompilujemy to z optymalizacja (np -O2)
[22:22] <@Gynvael>: to wtedy dostaniemy kod IDENTYCZNY Z KODEM:
[22:23] <@Gynvael>: printf("%i\n", 10);
[22:23] <@Gynvael>: ;p
[22:23] <@Gynvael>: czyli zmienna "x" po prostu nie bedzie istniala
[22:23] <@Gynvael>: jesli stosujemy jakies wysoce-hackerskie triki
[22:23] <@Gynvael>: to volatile warto dac zeby sie nie wysypalo przy optymalkach (zadko ktory wysoce-hackerski trik sie niewysypuje coprawda ;p)
[22:24] <@Gynvael>: register <=- to dajemy przed deklaracja zmiennej
[22:24] <@Gynvael>: register int a;
[22:24] <@Gynvael>: to jest PROSBA (nie rozkaz!) do kompilatora zeby w miare mozliwosci wrzucil zmienna "a" do jakiegos rejestru, a nie do pamieci
[22:24] <@Gynvael>: ta prosba NIE MUSI BYC SPELNIONA
[22:25] <@Gynvael>: ale moze.. wtedy zyskujemy niezlego boosta predkosci przy uzywaniu tej zmiennej
[22:25] <@Gynvael>: w sumie prawda jest taka ze "nowoczesne" kompilatory wrzucaja do rejestrow co sie da (przy kompilacji z optymalka)
[22:25] <@Gynvael>: po za tym jest jeszcze pare prefixow do funkcji typu
[22:25] <@Gynvael>: __stdcall __cdecl czy __fastcall
[22:26] <@Gynvael>: ale o tym mowil nie bede, natomiast odesle was do wykladu z asma #3
[22:26] <@Gynvael>: tam to bylo omawiane
[22:26] <@Gynvael>: ok
[22:26] <@Gynvael>: mniej wiecej tyle o co ciekawszych prefixach
[22:26] <@Gynvael>: pytanka ?
[22:26] <@Gynvael>: a to ja mam pytanie =^^=
[22:26] <@Gynvael>: ktos nie zasnal jeszcze? ;>
[22:27] lav: ja
[22:27] <@Gynvael>: o ;>
[22:27] <@Gynvael>: zawsze jest przynajmniej do kogo mowic ;>
[22:27] <@Gynvael>: ok
[22:27] <@Gynvael>: dobra
[22:27] <@Gynvael>: jeszcze chwile o dosc waznej rzeczy (2 bad ze wiekszosc usnela ;p)
[22:27] <@Gynvael>: mianowicie o ciekawych bledach podczas kompilacji
[22:28] <@Gynvael>: oraz o typowych bugach
[22:28] <@Gynvael>: ktore programisci robia ;>
[22:28] <@Gynvael>: http://gynvael.lunarii.org/temp/error_001.c
[22:28] <@Gynvael>: czasem zdarzy sie zapomniec "gdzies na gorze" srednika
[22:28] <@Gynvael>: problemu nie ma gdy program ma 3 linie
[22:29] <@Gynvael>: ale gdy ma 1000, gcc bardzo lubi wypisac jakies makabryczne ilosci errorow
[22:29] <@Gynvael>: np 320 errorkow
[22:29] <@Gynvael>: ;>
[22:29] <@Gynvael>: kazdy inny
[22:29] <@Gynvael>: 21:53:59 LiTeStEp >c error_001
[22:29] <@Gynvael>: [ CC ] error_001.exe
[22:29] <@Gynvael>: error_001.c:5: error: syntax error before "struct"
[22:29] <@Gynvael>: error_001.c:8: warning: ISO C does not allow extra `;' outside of a function
[22:29] <@Gynvael>: ERROR! Something went wrong!!!
[22:29] <@Gynvael>: przykladowo
[22:29] <@Gynvael>: gorny blad jest zrozumialy
[22:29] <@Gynvael>: blad skladni przed "struct" w linii 5tej
[22:29] <@Gynvael>: I TYLKO ON JEST WAZNY
[22:29] <@Gynvael>: kazdy nastepny blad jest zmyslony ;>
[22:30] <@Gynvael>: error_001.c:8: warning: ISO C does not allow extra `;' outside of a function
[22:30] <@Gynvael>: przykladowo ta informacja moze skolowac programiste
[22:30] <@Gynvael>: znam osoby ktore zamiast rzucic okiem na pierwszy blad, siedzialy po parenascie minut - pare godzin nad takimi bezsensownymi warningami/errorami "z dolu"
[22:31] <@Gynvael>: tak ze bardzo wazna rzecza jest zeby USUWAC BLEDY OD GORY ;>
[22:31] <@Gynvael>: (ofc ja jestem jedna z takich osob ktore przesiedzialy pare godzin nad tym ;pppppp)
[22:32] <@Gynvael>: http://gynvael.lunarii.org/temp/error_002.c
[22:32] <@Gynvael>: tam mamy troche inna bajke
[22:32] <@Gynvael>: mianowicie mamy zadeklarowany struct ala z jednym polem
[22:32] <@Gynvael>: a nastepnie w main mamy
[22:32] <@Gynvael>: ala b;
[22:32] <@Gynvael>: jest to bardzo czesty blad ktory robia programisci przechodzacy z C++ na C
[22:32] <@Gynvael>: error_002.c: In function `main':
[22:32] <@Gynvael>: error_002.c:12: error: `ala' undeclared (first use in this function)
[22:32] <@Gynvael>: error_002.c:12: error: (Each undeclared identifier is reported only once
[22:32] <@Gynvael>: error_002.c:12: error: for each function it appears in.)
[22:32] <@Gynvael>: error_002.c:12: error: syntax error before "b"
[22:32] <@Gynvael>: error_002.c:13: error: `b' undeclared (first use in this function)
[22:33] <@Gynvael>: kompilator jak widac wypisuje wtegy cala mase bledow
[22:33] <@Gynvael>: programista widzi ze mma
[22:33] <@Gynvael>: *ma
[22:33] <@Gynvael>: ala b;
[22:33] <@Gynvael>: czyli zadeklarowana zmienna b
[22:33] <@Gynvael>: a kompilator mu pisze
[22:33] <@Gynvael>: `b' undeclared (niezdeklarowana)
[22:33] <@Gynvael>: ma structa ala
[22:33] <@Gynvael>: struct ala
[22:33] <@Gynvael>: a kompilator mu pisze
[22:33] <@Gynvael>: `ala' undeclared
[22:33] <@Gynvael>: ;>
[22:34] <@Gynvael>: nalezy pamietac ze dla C nazwa structa nie jest "ala" tylko "struct ala" ;>
[22:34] <@Gynvael>: i nalezy robic struct ala b;
[22:34] <@Gynvael>: albo zrobic sobie
[22:34] <@Gynvael>: typedef struct ala ala;
[22:34] <@Gynvael>: i wtedy uzywac ala b; ;>
[22:34] <@Gynvael>: http://gynvael.lunarii.org/temp/error_003.c
[22:34] <@Gynvael>: podobna sytuacja
[22:34] <@Gynvael>: mamy struct ala
[22:34] <@Gynvael>: struct ala y, *x = &y;
[22:34] <@Gynvael>: x.kot = 12;
[22:34] <@Gynvael>: i cos takiego
[22:34] <@Gynvael>: czyli x jest POINTEREM
[22:34] <@Gynvael>: a programista napisal
[22:34] <@Gynvael>: x.kot = 12;
[22:35] <@Gynvael>: error_003.c:13: error: request for member `kot' in something not a structure or
[22:35] <@Gynvael>: union
[22:35] <@Gynvael>: kompilator wypisze cos takiego
[22:35] <@Gynvael>: czyli "zadanie czlonka 'kot' w czyms co nie jest ani struktura ani unia"
[22:35] <@Gynvael>: pierwsze co sie nasuwa na mysl to WTF
[22:35] <@Gynvael>: struct ala y, *x = &y;
[22:35] <@Gynvael>: przeciez x JEST struktura..
[22:36] <@Gynvael>: ale po przyjrzeniu sie blizej widac ze nie jest
[22:36] <@Gynvael>: jest ADRESEM STUKRUTY
[22:36] <@Gynvael>: czyli trzeba pisac x->kot = 12;
[22:36] <@Gynvael>: albo (*x).kot = 12;
[22:36] <@Gynvael>: ;>
[22:36] <@Gynvael>: w sumie tyle z errorow
[22:36] <@Gynvael>: teraz troche bugow
[22:36] <@Gynvael>: po kolei
[22:37] <@Gynvael>: 1) mowilem dzisiaj o static.. czasem sie zdarza ze niektorzy robia tak:
[22:37] <@Gynvael>: int
[22:37] <@Gynvael>: main(void)
[22:37] <@Gynvael>: {
[22:37] <@Gynvael>: int i;
[22:37] <@Gynvael>: i += 12;
[22:37] <@Gynvael>: printf("%i\n", i);
[22:37] <@Gynvael>: return 0;
[22:37] <@Gynvael>: }
[22:37] <@Gynvael>: liczac na to ze i na poczatku == 0..
[22:37] <@Gynvael>: "i" na poczatku NIE wynosi 0, ile wynosi ? zazwyczaj smieci
[22:37] <@Gynvael>: dosc latwo to zweryfikowac odpalajac ten program
[22:38] <@Gynvael>: 22:36:43 LiTeStEp >bug_001
[22:38] <@Gynvael>: 16396
[22:38] <@Gynvael>: 16396 to nie 12 ;>
[22:38] <@Gynvael>: ktorego sie spodziewalismy ;>
[22:38] <@Gynvael>: wiec albo int i = 0;
[22:38] <@Gynvael>: albo static int i;
[22:38] <@Gynvael>: ;>
[22:38] <@Gynvael>: 2) baaaaardzo czestym bledem poczatkujacych programistow jest proba zapisu czegos pod niepodany adres ;>
[22:39] <@Gynvael>: int
[22:39] <@Gynvael>: main(void)
[22:39] <@Gynvael>: {
[22:39] <@Gynvael>: char *string;
[22:39] <@Gynvael>: scanf("%s", string);
[22:39] <@Gynvael>: return 0;
[22:39] <@Gynvael>: }
[22:39] <@Gynvael>: coz
[22:39] <@Gynvael>: string nie jest wbrew pozora TABLICA O NIEOKRESLONEJ WIELKOSCI
[22:39] <@Gynvael>: tylko ADRESEM ZNAKU ;>
[22:40] <@Gynvael>: ten adres w kazdym badz razie jest prawie ze na pewno zly
[22:40] <@Gynvael>: jako ze jest to zmienna lokalna
[22:40] <@Gynvael>: a jak widzielismy w 1) zmienne lokalne maja smieci w sobie ;>
[22:40] <@Gynvael>: poprawnym zapisem powinno byc
[22:40] <@Gynvael>: char string[256];
[22:40] <@Gynvael>: scanf("%256s", string);
[22:41] <@Gynvael>: 3) czestym bledem jest podanie w scanf zamiast adresu zmiennej, jej wartosci ;>
[22:41] <@Gynvael>: int
[22:41] <@Gynvael>: main(void)
[22:41] <@Gynvael>: {
[22:41] <@Gynvael>: int i;
[22:41] <@Gynvael>: scanf("%i", i);
[22:41] <@Gynvael>: return 0;
[22:41] <@Gynvael>: }
[22:41] <@Gynvael>: scanf spodziewa sie adresu, i jako ze wszystko po "formacie" jest dodatkowym argumentem
[22:42] <@Gynvael>: to nie ma kontroli typu
[22:42] <@Gynvael>: wiec kompilator tego nie wykryje (te madre wykrywaja ;p)
[22:42] <@Gynvael>: natomiast wartosc "i" na pewno nie bedzie poprawnym adresem ;>>>>
[22:42] <@Gynvael>: (przy najmniej z punktu widzenia logicznego ;>)
[22:42] <@Gynvael>: poprawnym zapisem jest ofc: scanf("%i", &i);
[22:45] <@Gynvael>: 4) czestym bledem jest nie okreslenie wielkosci pola w scanf
[22:45] <@Gynvael>: int main(void)
[22:45] <@Gynvael>: {
[22:45] <@Gynvael>: unsigned char a[2] = {1,2};
[22:45] <@Gynvael>: scanf("%i", &a[0]);
[22:45] <@Gynvael>: printf("a[0] = %u, a[1] = %u\n",a[0], a[1]);
[22:45] <@Gynvael>: return 0;
[22:45] <@Gynvael>: }
[22:46] <@Gynvael>: przepraszam, wkleilem buga z bledem ;p
[22:46] <@Gynvael>: int main(void)
[22:46] <@Gynvael>: {
[22:46] <@Gynvael>: unsigned short a[2] = {1,2};
[22:46] <@Gynvael>: scanf("%u", &a[0]);
[22:46] <@Gynvael>: printf("a[0] = %u, a[1] = %u\n",a[0], a[1]);
[22:46] <@Gynvael>: return 0;
[22:46] <@Gynvael>: }
[22:46] <@Gynvael>: teraz jest ok ;>
[22:46] <@Gynvael>: ok
[22:46] <@Gynvael>: czyli tak
[22:46] <@Gynvael>: mamy tablice dwoch shortow
[22:46] <@Gynvael>: a[0] == 1, a[1] == 2
[22:47] <@Gynvael>: po czym chcemy do a[0] wczytac sobie liczbe
[22:47] <@Gynvael>: po czym wypisujemy obie liczby
[22:47] <@Gynvael>: 22:48:55 LiTeStEp >bug_004
[22:47] <@Gynvael>: 7
[22:47] <@Gynvael>: a[0] = 7, a[1] = 0
[22:47] <@Gynvael>: ale.. ? wtf ? ;>
[22:47] <@Gynvael>: "czemu w a[1] jest 0 a nie 2!!!" ;>
[22:47] <@Gynvael>: coz
[22:48] <@Gynvael>: scanf dostajac %u czy %i czy %d spodziewa sie dostac ADRES INTA, czyli adres 32bitowej zmiennej
[22:48] <@Gynvael>: short ma 16 bitow
[22:48] <@Gynvael>: wiec scanf dostaje adres a[0], 16sto bitowego shorta
[22:48] <@Gynvael>: a nastepne 16 bitow zajmuje a[1]
[22:48] <@Gynvael>: a scanf mysli ze dostal jednego 32 bitowego inta
[22:49] <@Gynvael>: wiec liczba ktora wczyta nadpisuje wartosci OBU zmiennych
[22:49] <@Gynvael>: a nie tylko a[0]
[22:49] <@Gynvael>: poprawnie powinno byc scanf("%hu", &a[0]);
[22:49] <@Gynvael>: 5) czestym bledem i bardzo trudnym do wysledzenia jest tzw memory leak
[22:50] <@Gynvael>: czyli zaalokowanie pamieci (malloc/calloc etc) a potem zapomnienie o free()
[22:50] <@Gynvael>: o ile nie problem jest to zobaczyc w 5cio linijkowym programie
[22:50] <@Gynvael>: to w projekcie na 10000 linii, z jakimis implementacjami drzew binarnych
[22:50] <@Gynvael>: cos takiego jest BARDZO TRUDNO wysledzic
[22:50] <@Gynvael>: wiec starac sie pamietac o tym
[22:50] <@Gynvael>: ;>
[22:51] <@Gynvael>: bo moze sie okazac ze systemowi sie pamiec skonczyla
[22:51] <@Gynvael>: ;p
[22:51] <@Gynvael>: 6) analogiczna sytuacja jak w 5), tyle ze za z plikami/socketami..
[22:51] <@Gynvael>: jesli naotwieramy plikow/socketow
[22:51] <@Gynvael>: i ich nie zamkniemy
[22:51] <@Gynvael>: to system moze stwierdzic ze juz nie ma zadnych dostepnych i nasz program badz inne aplikacje juz wiecej nie otworzy
[22:51] <@Gynvael>: pamietac wiec o fclose(), close() i closesocket() ;>
[22:52] <@Gynvael>: 7) czestym bledem jest rowniez overflow tablicy
[22:52] <@Gynvael>: przykladowo bardzo wielu poczatkujacych programistow (szczegolnie tych co przechodza z Pascala na C)
[22:52] <@Gynvael>: patrzac na deklaracje tablicy
[22:52] <@Gynvael>: int a[100];
[22:52] <@Gynvael>: mysli ze a ma indexy od a[1] do a[100] albo od a[0] do a[100]
[22:52] <@Gynvael>: to jest ofc blad, jako ze 100 jest ILOSCIA POL TABELI
[22:53] <@Gynvael>: ale pola sa liczone od [0]
[22:53] <@Gynvael>: czyli a[99] jest OSTATNIM POLEM TABELI
[22:53] <@Gynvael>: a a[100] to juz jest jakas inna zmienna w pamieci ;>
[22:53] <@Gynvael>: 8) czesto zdaza sie indexowanie tablicy zmiennymi o wartosciach ujemnych
[22:54] <@Gynvael>: pamietacie unsigned char dzialanie z poprzedniego zadanka ?
[22:54] <@Gynvael>: co by bylo gdybym zapomial dac "unsigned"
[22:54] <@Gynvael>: a user wklepal z klawiatury jakis znak powyzej 0x7f (127), np 0x80 (to jest -128 ;>)
[22:54] <@Gynvael>: wtedy gdy robilem if(funkcje[dzialanie]
[22:54] <@Gynvael>: to bym robil
[22:54] <@Gynvael>: if(funkcje[-128]
[22:55] <@Gynvael>: a to by oznaczalo segfault (bo funkcje byly w sekcji danych ktora jest niewielka) ;>
[22:55] <@Gynvael>: to nalezy do bledow trudnych do wysledzenia ;>
[22:55] <@Gynvael>: (mi i znajomemu to kiedys 2h zajelo --; gdzie sie czasnalem przy implementacji huffmana i 2h zeszlo ;>)
[22:56] <@Gynvael>: wymieniac tych czestych bledow mogl bym jeszcze sporo ;>
[22:56] <@Gynvael>: ale sadze ze te wystarcza
[22:56] <@Gynvael>: ok
[22:56] <@Gynvael>: pare uwag na zakonczenie kursu ;>
[22:56] <@Gynvael>: 1) kompilujcie zawsze gcc -Wall -pedantic ;>
[22:56] <@Gynvael>: 2) nie bojcie sie -std=c99, c99 to nowy standard C z paroma bardzo fajnymi featureami ;> warto sie tym zainteresowac ;>
[22:57] <@Gynvael>: 3) warto testowac programy nie tylko po normalnym skompilowaniu, ale rowniez po skompilowaniu -O2 albo -O3 (z optymalizajca).. wtedy niektore trudno wykrywalne bledy zademonstruja swe dzialanie ;>
[22:57] <@Gynvael>: 4) warningi sa po to zeby je usuwac ;> nei po to zeby zasmiecaly ekran przy kompilacji ;>
[22:59] <@Gynvael>: 5) czasem warto niektore programy przekompilowac na paru kompilatorach zeby zobaczyc czy nie zachowuja sie roznie, nie ma jakis bledow ktorych inny kompilator nie wykryl (przykladowo ja kompiluje na MinGW gcc, M$ VC++ i Pelles C ;>)
[22:59] <@Gynvael>: 6) THINK (to pisze przy wejsciu do siedziby IBM podobno;>)
[22:59] <@Gynvael>: 7) CONCENTRATE! (a to mowil moj sensei od kendo ;>)
[22:59] <@Gynvael>: ok
[22:59] <@Gynvael>: dziekuje za milo spedzony czas przez te 12 ostatnich wykladow ;>
[23:00] <@Gynvael>: i zapraszam na moje wyklady z Assemblera i z tworzenia gier w jezyku C ;>
[23:00] <@Gynvael>: komentarze na temat wykladu (co zmienic, co bylo OK) mozna wysylac (bezterminowo ;>) na <@Gynvael>@vexillium.org ;>
[23:00] <@Gynvael>: k, end ;>