[18:03] <@Gynvael> Witam wszystkich na pierwszym wykladzie w tym sezonie
[18:03] <@Gynvael> Coz ;> Widze ze sporo osob sie zebralo ;>
[18:04] <@Gynvael> Pierwszy wyklad bedzie przeznaczony raczej dla poczatkujacych programistow
[18:05] <@Gynvael> Postaram sie na nim przedstawic ide pointerow (wskaznikow) w jezyku C
[18:05] <@Gynvael> Pytania bedzie mozna zadawac jak wylacze moderacje
[18:05] <@Gynvael> postaram sie to robic wmiare czesto ;>
[18:05] <@Gynvael> OK ;> Wiec do roboty
[18:06] <@Gynvael> A, pol slowa jeszcze o mnie ;>
[18:06] <@Gynvael> Jestem studentem 3ciego (w sumie 4rtego) roku informatyki na Politechnice Wroclawskiej
[18:06] <@Gynvael> i jednoczesnie pracuje w jednej z polskich firm antywirusowych jako programista-reverser
[18:06] <@Gynvael> a po godzinach zajmuje sie gamedevem ;p
[18:07] <@Gynvael> ok tyle ;>

[18:07] <@Gynvael> Zaczne od malego wprowadzenia, ktore o raczej z sama skladnia C wspolnego nci nie ma
[18:07] <@Gynvael> to z samymi pointerami owszem ;>
[18:08] <@Gynvael> Wyobrazmy sobie ze mamy kartke papieru, w linie
[18:08] <@Gynvael> Linie sa ponumerowane, od 0 do 12 w tym wypadku
[18:08] <@Gynvael> zalozmy ze chcemy sobie na kartce napisac literki, od A do F
[18:09] <@Gynvael> a potem je w kolejnosci alfabetycznej wypisywac ;>

[18:09] <@Gynvael> W takim przypadku sprawa jest prosta
[18:09] <@Gynvael> Zaczynamy wypisywanie od zerowej linii
[18:09] <@Gynvael> I wypisujemy literki az do momentu gdy natrafimy na pusta linie
[18:10] <@Gynvael> czyli
[18:10] <@Gynvael> A B C D E F
[18:10] <@Gynvael> Zalozmy teraz ze przyszedl ktos, i nam troche te literki poprzestawial

[18:10] <@Gynvael> nie dosc ze zmienil kolejnosc (A C F B D E)
[18:10] <@Gynvael> to jeszcze porobil odstepy
[18:11] <@Gynvael> Gdybysmy wczesniejszy "algorytm" wypisywania chcieli zastosowac
[18:11] <@Gynvael> to wypisali bysmy jedynie literke A
[18:11] <@Gynvael> a nastepnie zakonczyli wypisywanie - bo natrafili bysmy na pusta linie
[18:11] <@Gynvael> Mozemy zmodyfikowac algorytm, tak zeby wypisywac tylko co druga linie
[18:11] <@Gynvael> wypiszemy wtedy A C F B D E..
[18:12] <@Gynvael> ale to nie spelnia naszego zaloze ze mamy wypisac literki W KOLEJNOSCI ALFABETYCZNEJ
[18:12] <@Gynvael> Sprobojmy wiec innego podejscia
[18:13] <@Gynvael> pogrupujmy wiec po dwie linie
[18:13] <@Gynvael> tak ze w pierwszej bedzie literka
[18:13] <@Gynvael> a w nastepnej NUMER LINII z nastepna w kolejnosci alfabetycznej literka

[18:14] <@Gynvael> I tak, oto
[18:14] <@Gynvael> najpierw jest literka A, po niej jest liczba 6
[18:15] <@Gynvael> ta liczba oznacza ze nastepna literka jest w linii numer szesc
[18:15] <@Gynvael> a jest tam B
[18:15] <@Gynvael> zaraz za B jest liczba 2
[18:15] <@Gynvael> w tejze (drugiej) linii jest literka C
[18:15] <@Gynvael> po ktorej jest liczba 8
[18:15] <@Gynvael> etc
[18:15] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr05.png

[18:16] <@Gynvael> Wypisywanie w 8 krokach wyglada tak:
[18:16] <@Gynvael> krok 1) idz do zerowej linii
[18:16] <@Gynvael> krok 2) wypisz literke A
[18:16] <@Gynvael> krok 3) idz do linii 6 i wypisz literke B
[18:17] <@Gynvael> krok 4) idz do linii 2 i wypisz literke C
[18:17] <@Gynvael> krok 5) idz do linii 8 i wypisz literke D
[18:17] <@Gynvael> krok 6) idz do linii 10 i wypisz literke E
[18:17] <@Gynvael> krok 7) idz do linii 4 i wypisz literke F
[18:18] <@Gynvael> krok 8) natrafiamy na pusta linie, koniec wypisywania
[18:18] <@Gynvael> wypisalismy wiec literki, w kolejnosci alfabetycznej
[18:18] <@Gynvael> Co to ma wspolnego z pointerami (wskaznikami) ?
[18:19] <@Gynvael> Ano tyle, ze te 'liczby' mowiace 'do ktorej linii isc dalej' to byly wskazniki
[18:19] <@Gynvael> Wskazywaly cos (linie z literka)
[18:20] <@Gynvael> I jedna wazna rzecz, odrazu "na wstepie". Wskaznik jest LICZBA.
[18:20] <@Gynvael> W pelni tego slowa znaczeniu.
[18:20] <@Gynvael> ok
[18:20] <@Gynvael> pytania do tej czesci ?
[18:20] <@_Arcan_> nie :P
[18:20] <@Robol> na razie nudno
[18:20] nie, chyba sie nie spóźniłem ??
[18:20] <@Robol> bo teorai
[18:20] Robol: jak mozesz
[18:20] <@WoLFy> ja mam ale dotyczace programu wykladu
[18:20] <@zettow> troche za dlugo sie ciagnie
[18:20] :/
[18:21] <@Robol> zaczynamy praktyke
[18:21] <@todevor> łe a moza to sobie tlumaczyc na c++?
[18:21] Gynvael: duzo przegapilem ?
[18:21] <@Reqamst> komentarze zostawcie na pozniej, plz
[18:21] <@WoLFy> bedzie cos na temat rzutowania wskaznikow?
[18:21] <@kamigo> nie mam wiecej pytan.
[18:21] Action: _OZZY_ mozeby tak ktos o socketach pod linuxa zazucil wyklad ??
[18:21] <@bartolomeo44> wlasnie, ile to bedzie trwalo?
[18:21] <@Gynvael> zaraz do praktyki przejdziemy
[18:21] ok. Ja nie mam więcej pytań
[18:21] <@Gynvael> do 19:30
[18:21] <@bartolomeo44> ok
[18:21] Ja bym chciał zauważyc ze mialy byc pytania ;p
[18:21] Action: todevor set +m
[18:21] <@Gynvael> WoLFy: bedzie
[18:21] Gynvael: ja cie blagam wylacz
[18:21] <@Reqamst> Gynvael: wez daj juz +m bo sie robi zamet niepotrzebny
[18:21] zrob ograniczona ilosc
[18:21] ludzi
[18:21] <@UrmeL> bedzie cos o tablicach?
[18:22] <@Gynvael> bedzie ;>
[18:22] bo co chwile ktos wlazi/wylazi
[18:22] <@Gynvael> dobra ;>
[18:22] <@fr3m3n> daj +i moze...
[18:22] dokladnie
[18:22] ;]
[18:22] <@Gynvael> jak by co to pytac na privie ;>
[18:22] <@Gynvael> +i ani +l nie bedize, natomiast proponuje zeby kazdy uzbroil sie w skrypty ignorujace PART/JOIN/QUIT na kanale
[18:22] <@Gynvael> w mircu w remote
[18:22] <@Gynvael> on ^*:JOIN:#wyklady:halt
[18:22] <@Gynvael> on ^*:PART:#wyklady:halt
[18:22] <@Gynvael> on ^*:QUIT:halt
[18:22] <@Gynvael> to zalatwia sprawe
[18:23] <@Gynvael> nie pamietam jak w irssi, ale /ignore #wyklady z jakimis opcjami
[18:23] <@Gynvael> ok
[18:23] <@Gynvael> przechodzimy dalej

[18:23] <@Gynvael> Jeszcze pare slow teorii, tym razem z 'systemow operacyjnych'
[18:24] <@Gynvael> Gdy skopilujemy program do postaci wykonywalnej (asdf.exe na przyklad, czy tam a.out ;>)
[18:25] <@Gynvael> w wiekszosci najczesciej uzywanych formatow plikow plik jest dzielony na 'sekcje' (PE, ELF)
[18:25] <@Gynvael> -=182538=- <@ved> na irssi: /ignore #wyklady XXX, gdzie XXX to do wyboru NICKS JOIN PART QUIT
[18:25] <@Gynvael> mamy sekcje KODU
[18:25] <@Gynvael> sekcje DANYCH
[18:25] <@Gynvael> sa tez inne sekcje, ale one nas nie obchodza
[18:26] <@Gynvael> w momencie kiedy uruchamiamy program
[18:26] <@Gynvael> system operacyjny tworzy PROCES
[18:26] <@Gynvael> 1) przydziela dla procesu pamiec
[18:26] <@Gynvael> 2) kopiuje KOD i DANE w odpowiednie miejsca w pamieci
[18:27] <@Gynvael> 3) przydziela pamiec na STOS dla procesu
[18:27] <@Gynvael> o pamieci najlepiej myslec jak o WIEEEELKIEJ tablicy bajtow (unsigned char)
[18:27] <@Gynvael> ktora zaczyna sie od 0 (jak nasze linie na kartce)
[18:27] <@Gynvael> i konczy baaaaardzo daleko ;>
[18:28] <@Gynvael> np na adresie 0xffffffff
[18:28] <@Gynvael> (nie bede sie wglebial zbytnio w teorie systemow operacyjnych)
[18:28] <@Gynvael> pamiec jest wielka, ale nasz program (proces) dostaje jej tylko maly fragment
[18:28] <@Gynvael> a raczej pare fragmentow
[18:28] <@Gynvael> i tylko do tej pamieci ma dostep
[18:29] <@Gynvael> przykladowo gdy kompilujemy cos pod windowsem za pomoca gcc (MinGW gcc, mingw.org)
[18:29] <@Gynvael> proces dostaje pamiec zaczynajaca sie od adresu 400000
[18:29] <@Gynvael> ok
[18:29] <@Gynvael> teraz czas na pierwszy progs
[18:30] <@Gynvael> program jest raczej krootki
[18:30] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr01.c
[18:30] <@Gynvael> #include
[18:30] <@Gynvael> int a = 0x13371337;
[18:30] <@Gynvael> int b = 0xDEADBABE;
[18:30] <@Gynvael>
[18:30] <@Gynvael> int
[18:30] <@Gynvael> main(void)
[18:30] <@Gynvael> {
[18:30] <@Gynvael> int c = 0xBAADC0D3;
[18:30] <@Gynvael> static int d = 0xABBAABBA;
[18:30] <@Gynvael> printf("liczba 'a' ma adres %p\n", &a);
[18:30] <@Gynvael> printf("liczba 'b' ma adres %p\n", &b);
[18:30] <@Gynvael> printf("liczba 'c' ma adres %p\n", &c);
[18:30] <@Gynvael> printf("liczba 'd' ma adres %p\n", &d);
[18:30] <@Gynvael> return 0;
[18:30] <@Gynvael> }
[18:31] <@Gynvael> o tak wyglada kod
[18:31] <@Gynvael> obojetnie jak duza jest pamiec zawsze od 400000 ?
[18:31] <@Gynvael> to od jakiego adresu jest, wybiera kompilator (i system operacyjny)
[18:32] <@Gynvael> nie zalezy to od ilosci RAMu w kompie ;> bo to sa adresy wirtualne (o tym kiedys indziej)
[18:32] <@Gynvael> ok
[18:32] <@Gynvael> program jak widac jest bardzo prosty
[18:32] <@Gynvael> sa 2 zmienne globalne (a, b)
[18:32] <@Gynvael> jedna lokalna i jedna lokalna statyczna (czyli globalna)
[18:33] <@Gynvael> zmienne maja wartosci napisane w Hexa
[18:33] <@Gynvael> takie dosc charakterystyczne wartosci
[18:33] <@Gynvael> 13371337
[18:33] <@Gynvael> marzenie nekrofila DEAD BABE
[18:33] <@Gynvael> przeklenstwo programisty BAAD C0D3
[18:33] <@Gynvael> i jakas reklama ABBA ABBA ;>
[18:33] <@Gynvael> program wypisuje ADRESY tych zmiennych
[18:34] <@Gynvael> Jesli mamy zmienna A
[18:34] <@Gynvael> to jej adres uzyskujemy za pomoca znaku REFERENCJI, czyli &
[18:34] <@Gynvael> &A <=- wynikiem tego dzialania jest LICZBA - ADRES A
[18:34] <@Gynvael> skompilujmy i odpalmy
[18:34] <@Gynvael> 17:55:39 >gcc ptr01.c -o ptr01
[18:34] <@Gynvael> 18:35:40 >ptr01
[18:34] <@Gynvael> liczba 'a' ma adres 00402000
[18:35] <@Gynvael> liczba 'b' ma adres 00402004
[18:35] <@Gynvael> liczba 'c' ma adres 0022FF74
[18:35] <@Gynvael> liczba 'd' ma adres 00402008
[18:35] <@Gynvael> 18:35:42 >
[18:35] <@Gynvael> U was adresy moga wygladac inaczej, wszystko zalezy od systemu operacyjnego i od kompilatora (i wersji kompilatora)
[18:36] <@Gynvael> U mnie pojawily sie takie adresy, i ich bede sie trzymal narazie ;>
[18:36] <@Gynvael> jak widac, zmienne 'a', 'b' i 'd' maja podobne adresy
[18:36] <@Gynvael> wszystkie zaczynaja sie od 004020??
[18:37] <@Gynvael> Nalezy tutaj przypomniec ze zmienna typu 'int' ma wielkosc 32 bity, czyli 4 bajty
[18:37] <@Gynvael> wiec
[18:37] <@Gynvael> 'a' ma adres 402000, 'b' ma adres o 4 wiekszy od 'a'
[18:37] <@Gynvael> czyli 402004
[18:37] <@Gynvael> Mozna wyciagnac (sluszny) wniosek ze te 4 bajty zajmuje zmienna 'a'
[18:38] <@Gynvael> potem jest na 402008 zmienna 'd'
[18:39] <@Gynvael> -=184005=- <@WoLFy> c znajduje sie na stosie funkcji a nie calego programu i to dlatego ma inny adres?
[18:39] <@Gynvael> tak
[18:39] <@Gynvael> zmienna 'c' ma zupelnie inny adres
[18:39] <@Gynvael> poniewaz znajduje sie w innej czesci pamieci
[18:39] <@Gynvael> a konkretniej w czesci zwanej 'stosem'
[18:40] <@Gynvael> stos to jest FRAGMENT PAMIECI (tablica) ktory sluzy do paru rzeczu:
[18:40] <@Gynvael> - przekazywania parametrow do funkcji
[18:40] <@Gynvael> - tam sa "alokowane" zmienne lokalne
[18:42] <@Gynvael> Przepraszam ;p
[18:42] <@Gynvael> -=184106=- <@Gynvael> stos to jest FRAGMENT PAMIECI (tablica) ktory sluzy do paru rzeczu:
[18:42] <@Gynvael> -=184116=- <@Gynvael> - przekazywania parametrow do funkcji
[18:42] <@Gynvael> -=184125=- <@Gynvael> - tam sa "alokowane" zmienne lokalne
[18:42] <@Gynvael> -=184228=- <@Gynvael> - przechowywania adresy powrotu z funkcji
[18:42] <@Gynvael> padlo pytanie
[18:42] <@Gynvael> co to jest %p
[18:42] <@Gynvael> %p w printf to jest wypisanie adresu - pointera
[18:42] <@Gynvael> w sumei jest to to samo co %x, %.8x albo %#x (to od kompilatora zalezy)
[18:42] <@Gynvael> czyli wypisanie wartosci hexadecymalnie
[18:43] <@Gynvael> Dlaczego akurat w hexa a nie dziesietnie ?
[18:43] <@Gynvael> Poniewaz 32 bity to dosc magiczna liczba, 32 bity == 4 bajty
[18:43] <@Gynvael> Jakos tak wszystko sie dookola tego kreci
[18:43] <@Gynvael> A np latwiej stwierdzic czy liczba w hexa dzieli sie przez 4
[18:43] <@Gynvael> powniewaz przez 4 dziela sie tylko liczby z koncowka 0, 4, 8 i C
[18:44] <@Gynvael> w dziesietnym trzeba by sprawdzac dwie ostanie cyfry ;>
[18:44] <@Gynvael> etc ;>
[18:44] <@Gynvael> ogolnie nalezy przyjac ze jest to wygodniejsze ;>
[18:44] <@Gynvael> Reqamst podal mi linka: to: http://pl.wikipedia.org/wiki/Printf
[18:44] <@Gynvael> tam o printf i %p mozna poczytac
[18:44] <@Gynvael> ok
[18:44] <@Gynvael> jedziemy dalej
[18:45] <@Gynvael> wiemy ze a, b, c, d maja jakies ADRESY
[18:45] <@Gynvael> sprawdzmy czy faktycznie zmienne sa tam gdzie mowia
[18:45] <@Gynvael> w tym celu mozna zrobic dwa rodzaje eksperymentow
[18:45] <@Gynvael> pierwszym z nich jest uruchomic Debugger (np OllyDbg pod windowsa, albo GDB pod linuxa)
[18:46] <@Gynvael> uruchomic program i zatrzymac w main()
[18:46] <@Gynvael> po czym kazac pokazac mu fragment pamieci
[18:46] <@Gynvael> w ktorym niby sa zmienne

[18:47] <@Gynvael> jest to zrzut ekranu z programu OllyDbg
[18:47] <@Gynvael> w lewym dolnym "oknie"
[18:47] <@Gynvael> mamy podglad pamieci
[18:47] <@Gynvael> jest tam adres, od 402000, i co 4 bajty wyswietla inty w HEXA
[18:48] <@Gynvael> liczba 'a' ma adres 00402000
[18:48] <@Gynvael> liczba 'b' ma adres 00402004
[18:48] <@Gynvael> liczba 'd' ma adres 00402008
[18:48] <@Gynvael> int a = 0x13371337;
[18:48] <@Gynvael> int b = 0xDEADBABE;
[18:48] <@Gynvael> static int d = 0xABBAABBA;
[18:48] <@Gynvael> prosze zauwazyc ze te wartosci faktycznie tam sa
[18:48] <@Gynvael> sa po sobie w pamieci
[18:48] <@Gynvael> pamiec sie na nich nie konczy (ani od nich nie zaczyna)
[18:49] <@Gynvael> sa tam jeszcze inne wartosci, ktorych pochodzenie jest dla nas narazie enigmetyczne ;>
[18:49] <@Gynvael> i moze takie pozostac ;>
[18:49] <@Gynvael> natomiast po prawej stronei na dole
[18:49] <@Gynvael> jest podglad stosu
[18:49] <@Gynvael> zaznaczony jest tam adres 22FF74, czyli adres zmiennej lokalnej 'c'
[18:50] <@Gynvael> int c = 0xBAADC0D3;
[18:50] <@Gynvael> jak widac pod tym adresem faktycznie ta zmienna jest
[18:52] <@Gynvael> drugim sposobem jest
[18:52] <@Gynvael> porownanie dwoch programow
[18:52] <@Gynvael> tj wynikow wypisywanych
[18:52] <@Gynvael> przez oba programy
[18:52] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr02.c
[18:52] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr03.c
[18:52] <@Gynvael> roznia sie one tym
[18:52] <@Gynvael> ze w ptr03.c
[18:53] <@Gynvael> zamiast zmiennych 'a', 'b', 'c', 'd' w dolnym wypisywaniu wartosci
[18:53] <@Gynvael> pojawily sie WCZESNIEJ ODCZYTANE wartosci adresow - pointerow
[18:53] <@Gynvael> printf("liczba 'a' ma wartosc %p\n", *(int*)0x00402000);
[18:53] <@Gynvael> printf("liczba 'b' ma wartosc %p\n", *(int*)0x00402004);
[18:53] <@Gynvael> printf("liczba 'c' ma wartosc %p\n", *(int*)0x0022FF74);
[18:53] <@Gynvael> printf("liczba 'd' ma wartosc %p\n", *(int*)0x00402008);
[18:53] <@Gynvael> etc
[18:53] <@Gynvael> jesli chcecie przeprowadzic ten eksperyment u siebie
[18:54] <@Gynvael> musicie zamienic te adresy na wartosci wypisywane u was
[18:54] <@Gynvael> wynik kompilacji i uruchomienia programu oryginalnego (ptr02) to u mnie:
[18:54] <@Gynvael> 18:35:42 >gcc ptr02.c -o ptr02
[18:54] <@Gynvael> 18:55:37 >ptr02
[18:54] <@Gynvael> liczba 'a' ma adres 00402000
[18:54] <@Gynvael> liczba 'b' ma adres 00402004
[18:54] <@Gynvael> liczba 'c' ma adres 0022FF74
[18:54] <@Gynvael> liczba 'd' ma adres 00402008
[18:54] <@Gynvael> liczba 'a' ma wartosc 13371337
[18:54] <@Gynvael> liczba 'b' ma wartosc DEADBABE
[18:54] <@Gynvael> liczba 'c' ma wartosc BAADC0D3
[18:54] <@Gynvael> liczba 'd' ma wartosc ABBAABBA
[18:54] <@Gynvael> 18:55:39 >
[18:55] <@Gynvael> a teraz wynik kompilacji i uruchomienia programu ptr03
[18:55] <@Gynvael> 18:55:39 >gcc ptr03.c -o ptr03
[18:55] <@Gynvael> 18:56:18 >ptr03
[18:55] <@Gynvael> liczba 'a' ma adres 00402000
[18:55] <@Gynvael> liczba 'b' ma adres 00402004
[18:55] <@Gynvael> liczba 'c' ma adres 0022FF74
[18:55] <@Gynvael> liczba 'd' ma adres 00402008
[18:55] <@Gynvael> liczba 'a' ma wartosc 13371337
[18:55] <@Gynvael> liczba 'b' ma wartosc DEADBABE
[18:55] <@Gynvael> liczba 'c' ma wartosc BAADC0D3
[18:55] <@Gynvael> liczba 'd' ma wartosc ABBAABBA
[18:55] <@Gynvael> 18:56:20 >
[18:55] <@Gynvael> jak widac wyniki sa identyczne
[18:56] <@Gynvael> pare slow o kodzie jeszcze
[18:56] <@Gynvael> *(int*)0x00402000
[18:56] <@Gynvael> taka konstrukcja sie pojawila
[18:56] <@Gynvael> 0x00402000 to jak pamietamy adres zmiennej 'a'
[18:56] <@Gynvael> (int*) to tzw rzutowanie (cast)
[18:56] <@Gynvael> chodzi o to by powiedziec kompilatorowi
[18:56] <@Gynvael> ze cos chcemy traktowac inaczej niz on by chcial ;>
[18:57] <@Gynvael> przykladem moze tu byc
[18:57] <@Gynvael> int a = 123;
[18:57] <@Gynvael> float b = (float)a;
[18:57] <@Gynvael> tutaj kazemy mu traktowac inta 'a' jak by byl liczba zmienna przecinkowa (tak naprawde zachodzi tu konwersja z int na float)
[18:57] <@Gynvael> (int*)0x00402000
[18:57] <@Gynvael> natomiast w naszym przypadku
[18:58] <@Gynvael> kazemy mu traktowac liczbe (inta badz co badz)
[18:58] <@Gynvael> 0x00402000
[18:58] <@Gynvael> jako int*
[18:58] <@Gynvael> int* jest to POINTER NA INTa
[18:58] <@Gynvael> czyli ADRES zmiennej int
[18:58] <@Gynvael> mimo ze adresy do floata, inta, etc fizycznie niczym sie nie roznia
[18:59] <@Gynvael> to rozni sie ich interpretacja po stronie kompilatora
[18:59] <@Gynvael> dodam tylko ze "ADRES DO CZEGOKOLWIEK" to w C void*, np void *ptr;
[18:59] <@Gynvael> na privie mi pare osob zglosilo ze sa warningi przy kompilacji przykladow
[19:00] <@Gynvael> sa, po prostu nie chcialem zaciemniac kodu niepotrzebnie usuwajac warningi zbednym rzutowaniem ;>
[19:00] <@Gynvael> ale wracajac do int*
[19:00] <@Gynvael> (int*)0x00402000
[19:00] <@Gynvael> czyli to to jest ADRES zmiennej typu int
[19:00] <@Gynvael> jest tam po lewej jeszcze gwiazdka
[19:00] <@Gynvael> *
[19:00] <@Gynvael> *(int*)0x00402000
[19:00] <@Gynvael> to oznacza
[19:00] <@Gynvael> "odczytaj to co jest pod adresem"
[19:00] <@Gynvael> czyli
[19:00] <@Gynvael> odczytaj to co jest pod adresem (int*)0x00402000
[19:01] <@Gynvael> co jest pod tym adresem ? to jest adres do inta, wiec jest to int
[19:01] <@Gynvael> czyli
[19:01] <@Gynvael> odczytaj int spod adresu....
[19:01] <@Gynvael> wartoscia wyrazenia *(int*)0x00402000 jest to co siedzi pod tym adresem
[19:01] <@Gynvael> czyli 13371337
[19:01] <@Gynvael> czyli wartosc zmiennej 'a'
[19:01] <@Gynvael> ok ;>
[19:01] <@Gynvael> 3 minuty przerwy
[19:01] <@Gynvael> wszelkie pytania na priva
[19:01] <@Gynvael> odpowiem na nie po przerwie
[19:06] <@Gynvael> ok
[19:06] <@Gynvael> pojawilo sie pytanie
[19:06] <@Gynvael> czym sie void od void* rozni
[19:06] <@Gynvael> void w C uzywany jest tylko w argumentach funkcji, i oznacza 'ta funkcja nie przyjmuje argumentow'
[19:06] <@Gynvael> z angielskiego bodajze void oznacza proznia/nicosc
[19:07] <@Gynvael> natomiast void* oznacza juz adres, czego adres ? prozni ;> a raczej, czegokolwiek ;>
[19:07] <@Gynvael> chodzi glownie o to ze kod:
[19:07] <@Gynvael> int a;
[19:07] <@Gynvael> char b;
[19:07] <@Gynvael> float c;
[19:07] <@Gynvael> void *v;
[19:07] <@Gynvael> v = &a;
[19:07] <@Gynvael> v = &b;
[19:07] <@Gynvael> v = &c;
[19:07] <@Gynvael> nie spowoduje warningow ani bledow
[19:08] <@Gynvael> pojawilo sie jeszcze inne pytanie
[19:08] <@Gynvael> skoro int ma 32 bity (4 bajty)
[19:08] <@Gynvael> char 1 bajt etc
[19:08] <@Gynvael> to ile ma adres bajtow ?
[19:09] <@Gynvael> jako ze adres, np int* void* etc
[19:09] <@Gynvael> to sa ZMIENNE
[19:09] <@Gynvael> to maja wielkosc
[19:09] <@Gynvael> KAZDY adres pod 32 bitowym systemem operacyjnym
[19:09] <@Gynvael> ma 32 bity
[19:09] <@Gynvael> czyli 4 bajty
[19:09] <@Gynvael> i bodajze ma 64 bity (8 bajtow) na 64-bitowych systemach
[19:09] <@Gynvael> ale za to glowy nie dam ;>
[19:10] <@Gynvael> ale na pewno nie ma 32 bitow tam;>
[19:11] <@Gynvael> ok
[19:11] <@Gynvael> lecimy dalej
[19:11] <@Gynvael> -=191231=- <@mi5tic> jedno pytanko... jest jakas roznica miedzy int* zmienna; a miedzy int *zmienna; ??
[19:11] <@Gynvael> to jest bardzo dobre pytanie
[19:11] <@Gynvael> roznicy nie ma zadnej
[19:11] <@Gynvael> ALE
[19:11] <@Gynvael> trzeba uwazac tutaj
[19:11] <@Gynvael> poniewaz
[19:12] <@Gynvael> przy deklaracji:
[19:12] <@Gynvael> int *a, b, c;
[19:12] <@Gynvael> tylko zmienna 'a' jest ADRESEM do INT
[19:12] <@Gynvael> zmienne B i C sa intami
[19:12] <@Gynvael> wiec jesli chcemy miec 3 pointery
[19:12] <@Gynvael> to piszemy
[19:12] <@Gynvael> int *a, *b, *c;
[19:12] <@Gynvael> pisanie
[19:13] <@Gynvael> int* a; mimo iz rownoznaczne int *a; moglo by sugerowac ze wszystkie zmienne po przecinku beda adresami
[19:13] <@Gynvael> trzeba na to uwazac ;>
[19:13] <@Gynvael> -=191426=- <@Reqamst_> http://www.research.att.com/~bs/bs_faq2.html#whitespace
[19:13] <@Gynvael> tam cos wiecej mozna o tym poczytac podobno ;>
[19:14] <@Gynvael> ok
[19:14] <@Gynvael> mowilem juz ze pointer jest LICZBA
[19:14] <@Gynvael> liczby mozna dodawac, odejmowac
[19:14] <@Gynvael> etc
[19:14] <@Gynvael> tak samo pointery
[19:14] <@Gynvael> to sie stosuje zadko, raczej dodaje sie inty (liczby calkowite) do pointerow
[19:14] <@Gynvael> albo inkrementuje/dekrementuje pointery
[19:14] <@Gynvael> rzucmu okiem na program kolejny
[19:15] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr04.c
[19:15] <@Gynvael> nowoscia tutaj sa nastepujace rzeczy:
[19:15] <@Gynvael> int *ptr = &a;
[19:15] <@Gynvael> to jest definicja zmiennej 'ptr', ktora jest adresem zmiennej int, i ma wartosc &a, czyli adres zmiennej 'a'
[19:16] <@Gynvael> potem jest ciag
[19:16] <@Gynvael> printf("ptr to liczba (adres) o wartosci %p\n", ptr);
[19:16] <@Gynvael> printf("ptr wskazuje na %p\n", *ptr);
[19:16] <@Gynvael> ptr++;
[19:16] <@Gynvael> printf("ptr to liczba (adres) o wartosci %p\n", ptr);
[19:16] <@Gynvael> printf("ptr wskazuje na %p\n", *ptr);
[19:16] <@Gynvael> ptr++;
[19:16] <@Gynvael> printf("ptr to liczba (adres) o wartosci %p\n", ptr);
[19:16] <@Gynvael> printf("ptr wskazuje na %p\n", *ptr);
[19:16] <@Gynvael> o takiego czegos
[19:16] <@Gynvael> najpierw wypisujemy wartosc ptr
[19:16] <@Gynvael> potem wypisujemy to co jest pod adresem 'ptr', czyli na co ptr wskazuje
[19:17] <@Gynvael> a potem inkrementujemy pointer
[19:17] <@Gynvael> i dalej to samo
[19:17] <@Gynvael> 19:18:22 >ptr04
[19:17] <@Gynvael> liczba 'a' ma adres 00402000
[19:17] <@Gynvael> liczba 'b' ma adres 00402004
[19:17] <@Gynvael> liczba 'c' ma adres 0022FF74
[19:17] <@Gynvael> liczba 'd' ma adres 00402008
[19:17] <@Gynvael> ptr to liczba (adres) o wartosci 00402000
[19:17] <@Gynvael> ptr wskazuje na 13371337
[19:17] <@Gynvael> ptr to liczba (adres) o wartosci 00402004
[19:17] <@Gynvael> ptr wskazuje na DEADBABE
[19:17] <@Gynvael> ptr to liczba (adres) o wartosci 00402008
[19:17] <@Gynvael> ptr wskazuje na ABBAABBA
[19:17] <@Gynvael> 19:18:23 >
[19:18] <@Gynvael> btw w moim przypadku kompilator ustawil zmienne a, b, d po sobie w pamieci, ale to zalezy od kompilatora i kodu tak naprawde ;>
[19:18] <@Gynvael> ok
[19:18] <@Gynvael> ale co sie dzieje
[19:18] <@Gynvael> pierwsze ciekawa rzecza jest inkrementacja
[19:18] <@Gynvael> <@Gynvael> ptr to liczba (adres) o wartosci 00402000
[19:18] <@Gynvael> <@Gynvael> ptr to liczba (adres) o wartosci 00402004
[19:18] <@Gynvael> <@Gynvael> ptr to liczba (adres) o wartosci 00402008
[19:18] <@Gynvael> ptr++;
[19:18] Last message repeated 1 time(s).
[19:18] <@Gynvael> prosze zauwazyc ze mamy inkrementacje (o 1)
[19:18] <@Gynvael> ale wartosc ptr zwieksza sie o 4
[19:19] <@Gynvael> mimo iz jest to troche irytujace dla programistow przyzwyczajonych np do assemblera
[19:19] <@Gynvael> to na dluzsza mete jest to wygodne
[19:19] <@Gynvael> o co w tym chodzi ?
[19:19] <@Gynvael> kompilator wie co sie znajduje pod ptr
[19:19] <@Gynvael> wie ze tam sie znajduje int
[19:19] <@Gynvael> skad wie ? bo ptr to wskaznik na inta
[19:19] <@Gynvael> wiec na co mial by wskazywac jesli nie na inta ?
[19:19] <@Gynvael> kompilator wie rowniez, ze int ma 32 bity (4 bajty)
[19:20] <@Gynvael> wiec wie, ze NASTEPNY int znajduje sie o 4 bajty dalej
[19:20] <@Gynvael> wiec tak naprawde
[19:20] <@Gynvael> ptr++ nie znaczy "zwieksz adres o 1"
[19:20] <@Gynvael> tylko "idz do nastepnego inta"
[19:20] <@Gynvael> ale w sensie "zwieksz adres o wielkosc inta (4)" a nie "wyszukaj inta"
[19:21] <@Gynvael> a pamieci wszystko to sa tylko liczby, takie rzeczy jak typy danych to sprawa kompilatora
[19:21] <@Gynvael> <@bartolomeo> ale ptr+=1; juz nie zinkrementuje tak jak trzeba?
[19:21] <@Gynvael> nie
[19:21] <@Gynvael> wszystkie operacje arytmetyczne na wskaznikach
[19:21] <@Gynvael> sa obarczone wagom - wielkoscia zmiennej wskazywanej
[19:21] <@Gynvael> czyli ptr+=1 rowniez zwiekszy wartosc wskaznika o 4
[19:22] <@Gynvael> odpalmy sobie program http://furio.vexillium.org/~wyklady/ptr/ptr06.c
[19:22] <@Gynvael> on wypisuje wielkosci zmiennych
[19:23] <@Gynvael> 19:23:53 >ptr06
[19:23] <@Gynvael> 'a' ma adres 00404080 i wielkosc 00000004 (4 dec)
[19:23] <@Gynvael> 'b' ma adres 004040B0 i wielkosc 00000004 (4 dec)
[19:23] <@Gynvael> 'c' ma adres 004040E0 i wielkosc 00000004 (4 dec)
[19:23] <@Gynvael> 'd' ma adres 004040C0 i wielkosc 00000002 (2 dec)
[19:23] <@Gynvael> 'f' ma adres 004040D0 i wielkosc 00000001 (1 dec)
[19:23] <@Gynvael> 'g' ma adres 00404090 i wielkosc 00000008 (8 dec)
[19:23] <@Gynvael> wezmy naprzyklad zmienna 'g', to jest double g;
[19:23] <@Gynvael> jesli bysmy zrobili sobei wskaznik
[19:23] <@Gynvael> double *ptr = &g;
[19:23] <@Gynvael> jak widac wyzej, g ma adres 00404090
[19:24] <@Gynvael> jesli napiszemy ptr += 2;
[19:24] <@Gynvael> to adres zmieni sie na 004040A0
[19:24] <@Gynvael> (przypominam ze to hexa)
[19:24] <@Gynvael> czemu ?
[19:24] <@Gynvael> poniewaz adres += adres * wielkosc(double)
[19:24] <@Gynvael> e
[19:24] <@Gynvael> poniewaz adres += 2 * wielkosc(double)
[19:25] <@Gynvael> czyli 004040A0 += 2 * 8
[19:25] <@Gynvael> 2 * 8 to 16, czyli 0x10
[19:25] <@Gynvael> wiec
[19:25] <@Gynvael> troche namieszalem
[19:25] <@Gynvael> czyli 00404090 += 2 * 8
[19:25] <@Gynvael> 2 * 8 to 16, czyli 0x10
[19:25] <@Gynvael> wiec
[19:25] <@Gynvael> 004040A0 wychodzi
[19:25] <@Gynvael> i teraz klaniaja sie casty
[19:25] <@Gynvael> czyli rzutowania
[19:26] <@Gynvael> mamy sobie double g;
[19:26] <@Gynvael> i mamy double *ptr = &g;
[19:26] <@Gynvael> i KONIECZNIE z jakiegos znanego tylko nam powodu chcemy zwiekszyc ptr o dokladnie 1, nie o 8, tylko o 1
[19:26] <@Gynvael> normalnie bysmy zrobili
[19:26] <@Gynvael> ptr++
[19:26] <@Gynvael> ale kompilator pojdzie o 8 bajtow dalej
[19:26] <@Gynvael> wiec
[19:26] <@Gynvael> przekonajmy kompilator
[19:27] <@Gynvael> ze ptr wskazuje na cos innego, nie na double (8 bajtow) tylko na char (1 bajt)
[19:27] <@Gynvael> tak zeby dodalo 1 przy inkrementacji
[19:27] <@Gynvael> wiec
[19:27] <@Gynvael> ((char*)ptr)++
[19:27] <@Gynvael> czyli
[19:27] <@Gynvael> ptr - wskaznik na double
[19:28] <@Gynvael> (char*)ptr - nee.. to jest tak naaaaapraaaaaawde wskaznik na char
[19:28] <@Gynvael> ((char*)ptr)++;
[19:28] <@Gynvael> zwiekszamy wskaznik na chara o 1 ;>
[19:28] <@Gynvael> ptr tak na prawde nie zmienil typu na stale
[19:29] <@Gynvael> tylko na chwile - na potrzebe tego jednego wyrazenia
[19:29] <@Gynvael> ok
[19:29] <@Gynvael> jedzmy dalej
[19:29] <@Gynvael> Tak sobie ty przyszedlem, mowie o wskaznikach
[19:29] <@Gynvael> ale po co one komu, oprocz utrudniania zycia ?
[19:30] <@Gynvael> wskazniki umieja to zycie rowniez umilic
[19:30] <@Gynvael> pare przykladow
[19:30] <@Gynvael> 1)
[19:30] <@Gynvael> mamy jakies dane
[19:30] <@Gynvael> nie wiemy ile ich jest
[19:30] <@Gynvael> i chcemy je wczytac do tablicy intow
[19:30] <@Gynvael> int tablica[???]
[19:30] <@Gynvael> noo i powstaje pytanie
[19:30] <@Gynvael> ile zaalokowac ?
[19:30] <@Gynvael> mozemy zaalokowac 1000 !
[19:30] <@Gynvael> ale co jesli danych bedzie 2000 ?
[19:31] <@Gynvael> no to dajmy tam 2000
[19:31] <@Gynvael> ale co jesli bedzie danych 4000 ?
[19:31] <@Gynvael> etc etc...
[19:31] <@Gynvael> zalozmy natomiast ze chwile przed wczytaniem danych
[19:31] <@Gynvael> poznajemy ich ilosc
[19:31] <@Gynvael> mozemy poprosic system o przyznanie nam potrzebnej ilosci pamieci
[19:31] <@Gynvael> sluzy do tego funkcja malloc (badz jej pochodne, sa tez inne, os-dep, ale zalozmy ze jest tylko malloc ;>)
[19:32] <@Gynvael> memory alloc.. malloc ;>
[19:32] <@Gynvael> malloc przyjmuje jeden argument, ile bajtow chcemy dostac
[19:32] <@Gynvael> i zwraca ADRES poczatku pamieci ktora system nam dal
[19:32] <@Gynvael> adres, czyli pointer
[19:32] <@Gynvael> przykladowy kod mogl by wygladac tak:
[19:33] <@Gynvael> int *tablica;
[19:33] <@Gynvael> int ilosc;
[19:33] <@Gynvael> scanf("%d", &ilosc);
[19:33] <@Gynvael> tablica = malloc(ilosc * sizeof(int));
[19:33] <@Gynvael> // tutaj jakis kod
[19:33] <@Gynvael> free(tablica);
[19:34] <@Gynvael> free oddaje systemowi pamiec gdy juz jej nie potrzebujemy ;>
[19:34] <@Gynvael> co bardziej uwazni dopatrza sie tutaj jeszcze jednego pointera
[19:34] <@Gynvael> scanf("%d", &ilosc);
[19:34] <@Gynvael> scanf tak na prawde przyjmuje ADRES pamieci w ktorym dana liczbe ma zapisac ;>
[19:36] <@Gynvael> pare osob na privie sie odezwalo
[19:36] <@Gynvael> pytajac czemu napisalem
[19:36] <@Gynvael> tablica = malloc(ilosc * sizeof(int));
[19:36] <@Gynvael> czy malloc zwraca int* ze to tak ladnie pasuje ?
[19:36] <@Gynvael> nie, malloc zwraca void* ;>
[19:36] <@Gynvael> czyli pointer na cokolwiek, jemu jest obojetne co my tam zapiszemy
[19:36] <@Gynvael> czemu wiec nie zrzutowalem tego na int* ?
[19:36] <@Gynvael> tablica = (int*)malloc(ilosc * sizeof(int));
[19:37] <@Gynvael> poniewaz w C nie trzeba rzutowac z i na void*
[19:37] <@Gynvael> ALE
[19:37] <@Gynvael> w C++ juz trzeba
[19:37] <@Gynvael> jesli wiec piszemy w C, to mozemy rzutowanie pominac
[19:37] <@Gynvael> ale jesli chcemy pisac w C++, albo pisac w C tylko chwile i przejsc na C++
[19:37] <@Gynvael> to to rzutowanie nalezy tam dawac ;>
[19:37] <@Gynvael> w C ono nie zaszkodzi ;> (ale i nie pomoze)
[19:38] <@Gynvael> o jeszcze jedno pytanie
[19:38] <@Gynvael> void *ptr = &g;
[19:38] <@Gynvael> ptr++;
[19:38] <@Gynvael> co sie stanie ? o ile zwiekszy sie ptr ?
[19:38] <@Gynvael> nie wiadomo ile wielkosci ma void przeniez
[19:38] <@Gynvael> ano, nie wiadomo ;> dlatego to jest blad ;>
[19:38] <@Gynvael> kompilator zwroci nam error ;>
[19:39] <@Gynvael> mozna natomiast zrobic
[19:39] <@Gynvael> ((char*)ptr)++; oczywiscie ;>
[19:39] <@Gynvael> ok
[19:39] <@Gynvael> jedziemy dalej bo czas ucieka
[19:40] <@Gynvael> jako ze juz widze ze czasu nie starczy
[19:40] <@Gynvael> to powiem tak
[19:40] <@Gynvael> po wykladzie na naszym forum
[19:40] <@Gynvael> a konkretniej http://forum.wyklady.net/index.php?topic=18.0
[19:40] <@Gynvael> tam
[19:40] <@Gynvael> bedzie mozna ocenic ten wyklad etc
[19:40] <@Gynvael> materialu o pointerach jest jeszcze na jeden wyklad
[19:41] <@Gynvael> wiec po wykladzie jesli ktos bedzie zainteresowany jeszcze jednym wykladem o zastosowaniu pointerow
[19:41] <@Gynvael> to prosze tam sie wpisac ;>
[19:41] <@Gynvael> ale narazie jedziemy dalej
[19:41] <@Gynvael> Co w C ma adres ?
[19:41] <@Gynvael> wiemy ze zmienne maja adresy
[19:41] <@Gynvael> adresy maja takze:
[19:41] <@Gynvael> 1) struktury (w sensie zmienne typu struktura ;>)
[19:41] <@Gynvael> 2) funkcje
[19:42] <@Gynvael> 3) stringi ;>
[19:42] <@Gynvael> "ala ma kota"
[19:42] <@Gynvael> to jest adres ;>
[19:42] <@Gynvael> (const char*) (w sumie to const char[])
[19:42] <@Gynvael> latwo to mozna sprawdzic
[19:42] <@Gynvael> np piszac
[19:42] <@Gynvael> printf("adres napisu: %p\n", "ala ma kota");
[19:42] <@Gynvael> albo probojac dodawac cos do tego i obserwujac efekt
[19:42] <@Gynvael> np
[19:43] <@Gynvael> puts("ala ma kota" + 4);
[19:43] <@Gynvael> to ostatnie wypisze 'ma kota' ;>
[19:43] <@Gynvael> ok
[19:43] <@Gynvael> funkcje tez maja wlasne adresy
[19:43] <@Gynvael> o tym za chwile
[19:43] <@Gynvael> 4) tablice
[19:43] <@Gynvael> pobawmy sie chwile tablicami
[19:44] <@Gynvael> http://furio.vexillium.org/~wyklady/ptr/ptr07.c
[19:44] <@Gynvael> to jest bardzo krotki program
[19:44] <@Gynvael> inicjacja tablicy 7 elementow
[19:45] <@Gynvael> wypisujemy 8 elementow (jak wiemy pamiec jest ciagla, i nie konczy sie na naszej tablicy, wiec mozemy sobie rzucic okiem co jest po tablicy)
[19:45] <@Gynvael> 19:23:56 >gcc ptr07.c -o ptr07
[19:45] <@Gynvael> 19:46:13 >ptr07
[19:45] <@Gynvael> tab[0] = 1
[19:45] <@Gynvael> tab[1] = 2
[19:45] <@Gynvael> tab[2] = 3
[19:45] <@Gynvael> tab[3] = 4
[19:45] <@Gynvael> tab[4] = 5
[19:45] <@Gynvael> tab[5] = 6
[19:45] <@Gynvael> tab[6] = 7
[19:45] <@Gynvael> tab[7] = 2293672
[19:45] <@Gynvael> 19:46:15 >
[19:46] <@Gynvael> a teraz rzucmy okiem na http://furio.vexillium.org/~wyklady/ptr/ptr08.c
[19:46] <@Gynvael> bardzo podobny program
[19:46] <@Gynvael> ktory dodatkowo wypisuje pare rzeczy
[19:46] <@Gynvael> 19:46:15 >gcc ptr08.c -o ptr08
[19:46] <@Gynvael> 19:47:32 >ptr08
[19:46] <@Gynvael> tab ma adres 0022FF50
[19:46] Last message repeated 1 time(s).
[19:46] <@Gynvael> tab[0] ma adres 0022FF50
[19:46] <@Gynvael> tab[1] ma adres 0022FF54
[19:46] <@Gynvael> *ptr = 1
[19:46] <@Gynvael> *ptr = 2
[19:46] <@Gynvael> *ptr = 3
[19:46] <@Gynvael> *ptr = 4
[19:46] <@Gynvael> *ptr = 5
[19:46] <@Gynvael> *ptr = 6
[19:46] <@Gynvael> *ptr = 7
[19:46] <@Gynvael> *ptr = 2293672
[19:46] <@Gynvael> 19:47:33 >
[19:47] <@Gynvael> jak widac
[19:47] <@Gynvael> printf("tab ma adres %p\n", tab);
[19:47] <@Gynvael> printf("tab ma adres %p\n", &tab);
[19:47] <@Gynvael> printf("tab[0] ma adres %p\n", &tab[0]);
[19:47] <@Gynvael> te 3 linie zwrocily dokladnie ten sam adres
[19:47] <@Gynvael> jest to odpowiedz na niezadane pytanie - jak uzyskac adres tablicy
[19:47] <@Gynvael> sposobow jest jak widac pare
[19:48] <@Gynvael> sama nazwa zmiennej - tablicy - jest jej adresem, a konkretniej
[19:48] <@Gynvael> adresem pierwszego elementu
[19:48] <@Gynvael> &tab <=- tak mozemy pisac, ale raczej bym odradzal
[19:48] <@Gynvael> &tab[0] <=- adres zerowego elementu
[19:48] <@Gynvael> -=194741=- <@Gynvael> tab[0] ma adres 0022FF50
[19:48] <@Gynvael> -=194741=- <@Gynvael> tab[1] ma adres 0022FF54
[19:48] <@Gynvael> to jest tablica intow
[19:48] <@Gynvael> wiec logicznym jest fakt
[19:48] <@Gynvael> ze kazdy element tablicy ma kolejny adres( 0 4 8 C etc...)
[19:49] <@Gynvael> czyli te elementy sa ulozone po sobie w pamieci
[19:49] <@Gynvael> int *ptr;
[19:49] <@Gynvael> ...
[19:49] <@Gynvael> ptr = tab;
[19:49] <@Gynvael> for(i = 0; i < 8; i++)
[19:49] <@Gynvael> printf("*ptr = %i\n", *ptr++);
[19:49] <@Gynvael> ptr to jest wskaznik na int*
[19:49] <@Gynvael> tab to jest tablica, ale jak mowilem, tab to jest tez adres tablicy, czyli wskaznik na pierwszy element, czyli tab tez jest int *
[19:50] <@Gynvael> (konkretniej bodajze int const *, czyli staly wskaznik na zmienna wartosc ;>)
[19:50] <@Gynvael> napisanie tab++; konczy sie bledem kompilacji ;>
[19:50] <@Gynvael> wiec
[19:50] <@Gynvael> ptr wskazuje na pierwszy element tablicy
[19:50] <@Gynvael> i pokolei wypisujemy co jest pod tym adresem (adresem elementu tablicy) *ptr
[19:50] <@Gynvael> i inkrementujemy ptr++, czyli *ptr++
[19:51] <@Gynvael> (jesli bysmy chcieli zwiekszyc element na ktory wskazuje ptr, to trzeba pisac (*ptr)++)
[19:51] <@Gynvael> te smieci w ostatnim elemencie
[19:51] <@Gynvael> <@Gynvael> tab[7] = 2293672
[19:51] <@Gynvael> sa w sumie zalezne od kompilatoar ;>
[19:51] <@Gynvael> one po prostu tam sa, cos znacza na pewno ;>
[19:51] <@Gynvael> ale nie trzeba wnikac co ;>
[19:51] <@Gynvael> ok
[19:51] <@Gynvael> czas dobiega konca
[19:52] <@Gynvael> jesli wykazecie na forum swoje zainteresowanie druga czescia wykladu o pointerach
[19:52] <@Gynvael> to druga czesc sie odbedzie ;>
[19:52] <@Gynvael> bylo by w niej:
[19:52] <@Gynvael> - troche wiecej dziwnych rzutowan
[19:52] <@Gynvael> - wskazniki do funkcji
[19:52] <@Gynvael> - wskazniki do struktur - proste dynamiczne struktury danych - linked listy
[19:53] <@Gynvael> - troche przykladow z zycia uzywania wskaznikow
[19:53] <@Gynvael> wyklad mozna ocenic i komentowac tam -> http://forum.wyklady.net/index.php?topic=18.0
[19:53] <@Gynvael> dziekuje wszystkim za udzial ;>
[19:54] <@Gynvael> logi i materialy z wykladu w ciagu paru dni (moze dzisiaj ;p) pojawia sie na http://wyklady.net
[19:54] <@Gynvael> A zainteresowanych zapraszam za 10 minut na wyklad o kompresji danych
[19:54] <@Gynvael> dziekuje