[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 ;>