Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 28 mar 2024, o 14:45


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 10 ] 
Autor Wiadomość
PostNapisane: 14 kwi 2012, o 22:34 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 paź 2011
Posty: 39
Lokalizacja: Łódź
Pomógł: 0

Witam Wszystkich! Pisze na forum bo już nie mam sumienia truć Mirkowi... Sprawa jak mnie nurtuje od dłuższego czasu to kopia wskaźnika. Dokładnie mówiąc stron 254 II wydania na samym dole. Moje rozumowanie jest takie:
Mamy zmienną:
uint8_t a = 10
załóżmy że ląduje pod adresem 0x01
potem mamy wskaźnik na tą zmienną

uint8_t *b = a
załóżmy że ląduje pod adresem 0x02
czyli b = 0x01

teraz robimy kopie wskaźnika
uint8_t *c = b
załóżmy że ląduje pod adresem 0x03
według mojego rozumowania wskaźnik c wskazuje na komórkę pamięci wskaźnika b więc w tej komórce powinien się znaleźć adres komórki b czyli 0x02, a nie 0x01:
czyli c = 0x02

Myślałem do tej pory że aby zrobić kopię wskaźnika trzeba zapisać:
uint8_t *c = *b

Czy może kompilator wie, że b jest wskaźnikiem i nie wpisuje w c adresu komórki wskaźnika b lecz ten adres na który wskazuje ponieważ właśnie jest wskaźnikiem?
Przewertowałem całą teorie w książce i nie znalazłem tam nic na temat kopwiowania wskaźników więc stąd mój problem.
Drugie pytanie to po co w tym przypadku (str 254) zastosowano kopie wskaźnika? Oba wskaźniki wskazują na jedną i tę samą komórke pamięci więc czy nie można operować na samym wskaźniku *str? Nie pytam dlatego że się czepiam ale wydaje mi się że był to celowy zabieg i dokładniejsze poznanie tematu nauczyłby mnie dobrych nawyków. Bo jak potem jakiś nawyk trzeba będzie zmienić będzie o wiele trudniej :)

Serdecznie pozdrawiam!



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2012, o 09:52 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

No wszystko ładnie pięknie tylko koledze umknęła pewna rzecz albo nawet dwie rzeczy (ale nie ma co się martwić - na początku przy wskaźnikach chyba każdy tak ma) - bo:

jeśli:

Kod:
uint8_t a = 10


i załóżmy że jak mówisz (to tylko założenie i tego się nie trzymamy sztywno w C) adres fizyczny to 01

to jeśli chcesz zrobić wskaźnik na tą zmienną to MUSISZ się posłużyć operatorem wyciągania adresu & (znak AND) (to pierwsze co przeoczyłeś) ... czyli:

Kod:
uint8_t *b = &a


i teraz UWAŻAJ - druga rzecz jaką przeoczyłeś (a jest o tym w książce też na pewno), że KAŻDY wskaźnik zajmuje w pamięci 2 bajty !!! to bardzo ważne - 2 bajty. To jest miejsce na adres w pamięci, który może przyjmować wartości od 0 do 65535 - o tym nie można zapominać.

dlatego nie można tego tak sobie opisać:

Cytuj:
załóżmy że ląduje pod adresem 0x02
czyli b = 0x01

teraz robimy kopie wskaźnika
uint8_t *c = b
załóżmy że ląduje pod adresem 0x03


bo już wskaźnik c będzie (załóżmy) pod adresem 04 .... to ważne a co jeszcze ważniejsze spójrz, skoro b to wskaźnik to tylko dlatego mogłeś zrobić:

uint8_t *c = b; -----> widzisz ? tak można bo do c (wskaźnika 2 bajtów) wpisujesz od razu adres 16-bitowy b - więc nie trzeba było operatora wyciągania adresu jak przy

uint8_t *b = &a; -----> tutaj gdybyś nie użył & to dostałbyś warninga. Bo bez operatora & to ty chciałbyś pod wskaźnik (adres) b zapisać WARTOŚĆ zmiennej a czyli 10, a nie adres pod którym ta zmienna się znajduje ;)

Spójrz sobie zresztą na pierwsze rysunki w rozdziale "WSKAŹNIKI" - one powinny pomóc


no i na koniec:

Cytuj:
Myślałem do tej pory że aby zrobić kopię wskaźnika trzeba zapisać:
uint8_t *c = *b


taki zapis znowu oznaczałby że ty do wskaźnika c chcesz zapisać to na co wskazuje wskaźnik b (bo dałeś gwiazdkę przed b) ..... a nie adres b

gwiazdka w przypadku definicji

Kod:
uint8_t *c


mówi tylko o tym, że to jest definicja wskaźnika !!!

ale w kodzie później:

*c - oznacza to na co wskazuje wskaźnik

a

c - oznacza fizyczny adres

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2012, o 12:20 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 paź 2011
Posty: 39
Lokalizacja: Łódź
Pomógł: 0

Witaj Mirek!
Dzięki za wyjaśnienia. O dwubajtowości wskaźnika pamiętam (bo przeczytałem rozdział o wskaźnikach chyba już z 8 razy :) ) tutaj rzeczywiście podałem przez omyłkę zły adres komórki pamięci - dzięki za sprostowanie. Wydaje mi się jednak że mój problem polega na złym rozumowaniu definiowaniu i jednoczesnym inicjowaniu wskaźnika. Definiujemy sobie zmienną i wskaźnik ale inicjujemy od razu tylko zmienną:
Kod:
uint8_t a = 10;
uint8_t *b;

i wtedy rozumiem że aby wskazać na zmienną a za pomocą wskaźnika b trzeba:
Kod:
b = &a
- bo jak damy gwiazdkę przy b to odwołamy się do jakiejś tam komórki której losowy adres przechowuje niezainicjowana komórka pamięci wskaźnika b i będzie błąd bo będziemy próbowali wrzucić dwa bajty do zmiennej jednobajtowej (z definicji wskaźnika uint8_t) zgadza się?

Dlatego aby coś zapisać do a mogę się posługiwać na przemiennie:
Kod:
a = 11 lub *b = 11


a jeśli definiujemy wskaźnik i od razu go inicjujemy to piszemy tak ??:
Kod:
uint8_t *b = &a

a po definicji tak??:
Kod:
 b = &a

Sądziłem że kompilator przy definicji wskaźnika i jego jednoczesnym inicjowaniu sam "wyciągnie" adres zmiennej na jaką ma wskazywać. Dalsze postępowanie ze wskaźnikami rozumiem problem mam tylko z ich definicją i jednoczesną inicjacją - jeśli dobrze posługuję się tutaj słowem inicjacja.

Proszę odpowiedz jeszcze na pytanie z pierwszego postu: po co stosuje się kopie wskaźników?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2012, o 13:09 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

DOKŁADNIE po definicji tak jak napisałeś ;) zobacz zresztą - zrobiłeś teraz wręcz fajny wykład na ten temat - czyli potwierdza się to co ja zawsze mówię że gdy chcemy kogoś nauczyć to sami się jeszcze 2x więcej uczymy ;) .... zatem życzę więcej takich fajnych wykładów - poważnie takie rozważanie tutaj to fajne uzupełnienie do książki i będę ten wątek polecał innym na forum ;)

"po co stosuje się kopie wskaźników?" ..... hm tak z gruszki bez jakiegoś przykładu to ciężko nieraz wprost odpowiedzieć, ale może coś podpowie ci zasada działania np funkcji strtok_r() lub podobnych gdzie jednym z argumentów jest wskaźnik do wskaźnika ;) czyli niejako przekazujemy kopię wskaźnika ;) .... Opisałem wykorzystanie tego w praktyce w książce w rozdziale dotyczącym Ethernetu przy komunikacji UDP ....

ale są też inne funkcje przyjmujące podobne argumenty - gdzie wyglądają mniej więcej np tak:
void fun( char ** s);

;) fajnie co ?

a tak jeśli chodzi o proste przykłady typu że b wskazuje na zmienną a natomiast c wskazuje na b - to nic do głowy mi na gorąco nie przychodzi. Na co dzień rzadko się raczej korzysta ze wskaźników do wskaźników - to już raczej w jakichś bardziej zakręconych przypadkach gdzie nie ma innego wyjścia i właśnie dopiero wskaźniki mogą nas wybawić z opresji ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 18:07 
Offline
Użytkownik

Dołączył(a): 01 cze 2012
Posty: 72
Lokalizacja: Gdańsk
Pomógł: 2

Przepraszam, że odkopuję temat wskaźników. Od kilku dni mam z tym wielki problem. To co tutaj napisaliście jest bardzo pouczające i cieszę się, że taki temat już się pojawił. Sama idea wskaźników jest mi znana i wydawała się prosta doputy, dopuki nie zacząłem analizować czyiś kodów.

Wiadomo, że wskaźnik to nic innego jak zmienna przechowująca adres pamięci do jakieś zmiennej. Natomiast taki zapis:
Cytuj:
void funkcja (char *wskaznik)

oznacza, że informujemy kompilator, że do funkcji przekazujemy argumenty w postaci adresu, prawda? W takim razie, wywołując wyżej wymienioną funkcje, stosujemy taki zapis:
Cytuj:
funkcja(@zmienna_a); //operator pobierania adresu @
//albo
funkcja(tablica); //tablica bez nawiasów zwraca asdres pierwszego elementu

(Wybczcie, że powtarzam wyżej zawarte informacje. Osobie, która to będzie czytać, bedzię łatwiej znależć miejsce, w którym zaczynam się gubić)
Równie dobrze można przekazać zmienną do tej funkcji, ale trzeba zadbać, aby ta zmienna była dwu bajtowa, prawda?
Cytuj:
int zmienna;
funkcja(zmienna);

Teraz, analizując czyjeś kody, znalazłem taki zapis:
Cytuj:
float* tab_wsk_liczb [ 10 ] ;

WYDAJE mi się, że jest to definicja tablicy 10-ciu wskaźników . Jeżeli to prawda, to jak to wykorzystać? Jeżeli tablica przechowuje adresy do różnych zmiennych, to nie można zrobić po prostu tak?:
Cytuj:
int tablica_adres [10];
tablica_adres[2] = @jakas_zmienna;
zmienna_b = *tablica[2];

Czy taki zapis jest prawidłowy?

Nie jestem wstanie zliczyć ile razy przeczytałem rozdział dotyczący wskaźników (przypuszczam, że mógłbym go wyrecytować, nawet jakby ktoś mnie obudził w środku nocy :D). Zacząłem się gubić, jak zobaczyłem połączenie struktur ze wskaźnikami, ale po kolei. Proszę szanownych kolegów wskazanie mi gdzie popełniam błąd w rozumowaniu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 18:50 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

bartool napisał(a):
Równie dobrze można przekazać zmienną do tej funkcji, ale trzeba zadbać, aby ta zmienna była dwu bajtowa, prawda?
Cytuj:
int zmienna;
funkcja(zmienna);


No już tu się gubisz Pan ;) ..... Bo skąd ci to przyszło do głowy? A poza tym jak zadajesz takie pytania nawet sam sobie - to zawsze weź Eclipse w łapki i dawaj!.... wprowadź taką definicję funkcji do której przekazujesz wskaźnik a potem spróbuj tak przekazać argument i skompiluj - popatrz co się stanie, jakie posypią się warningi itp - a nie tylko tak na sucho rozpatrujesz ;)

Jak można do funkcji fun( char * s ) przekazać

Kod:
int zmienna;
fun(zmienna);


toż to niestety totalne nieporozumienie - nawet jakbyś chciał tak:

Kod:
fun( &zmienna );


to też już miałbyś warningi przecież argument jest wskaźnikiem typu char a ty chcesz przekazać adres zmiennej typu int ??? czy sam nie widzisz w tym ZONKA ? ;) .... przecież funkcja będzie oczekiwała na wskaźnik char a ty jej wciskasz do gardła adres (wskaźnik) zmiennej typu int !!! i już masz niezgodność wskaźników. Oczywiście mógłbyś temu zapobiec robiąc jawne rzutowanie typu wskaźnikowego np tak:

Kod:
fun( (char*)&zmienna );


no ale czy wiesz co będzie tego efektem ? to zadziała - ale jeśli nie wiesz jak to tego nie rób bo się przejedziesz


bartool napisał(a):
Teraz, analizując czyjeś kody, znalazłem taki zapis:
Cytuj:
float* tab_wsk_liczb [ 10 ] ;

WYDAJE mi się, że jest to definicja tablicy 10-ciu wskaźników .


Dobrze ci się wydaje ale zobacz jakie są ważne szczegóły - nie dokończyłeś tej definicji a to pokazuje że nie zaskoczyłeś co to są albo po co w ogóle deklaruje się TYPY wskaźników. Zatem o tej tablicy powinieneś napisać tak:

WYDAJE mi się, że jest to tablica 10-elementowa w której każdy element jest wskaźnikiem typu int


bartool napisał(a):
Jeżeli to prawda, to jak to wykorzystać? Jeżeli tablica przechowuje adresy do różnych zmiennych, to nie można zrobić po prostu tak?:
Cytuj:
int tablica_adres [10];
tablica_adres[2] = @jakas_zmienna;
zmienna_b = *tablica[2];

Czy taki zapis jest prawidłowy?


Niepotrzebnie tworzysz taki reveres-engeneering, no i znowu się mylisz, wyżej podałeś przykład tablicy wskaźników a sam podajesz przykład zwykłej tablicy, czy ty nie widzisz różnicy w zapisach:

Kod:
float* tab_wsk_liczb [ 10 ]

int tablica_adres [ 10 ];


poza tym że różnią się typem ??????????

przecież w twoim przykładzie brakuje gwiazdki a zatem twoja tablica to już nie jest tablica wskaźników tylko tablica 10-elementowa gdzie każdy element jest typu int. Co to ma wspólnego ze wskaźnikiem?

dlatego w takim przypadku twój zapis:

Kod:
tablica_adres[2] = @jakas_zmienna;


oczywiście wywoła agresję kompilatora i będzie on miał rację, chyba żebyś zmienił tablicę na taką:

Kod:
int * tablica_adres [ 10 ];


widzisz tą subtelną różnicę ????

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 20:24 
Offline
Użytkownik

Dołączył(a): 01 cze 2012
Posty: 72
Lokalizacja: Gdańsk
Pomógł: 2

Cytuj:
No już tu się gubisz Pan ..... Bo skąd ci to przyszło do głowy? A poza tym jak zadajesz takie pytania nawet sam sobie - to zawsze weź Eclipse w łapki i dawaj!.... wprowadź taką definicję funkcji do której przekazujesz wskaźnik a potem spróbuj tak przekazać argument i skompiluj - popatrz co się stanie, jakie posypią się warningi itp - a nie tylko tak na sucho rozpatrujesz

Jak można do funkcji fun( char * s ) przekazać
Kod:
int zmienna;
fun(zmienna);

toż to niestety totalne nieporozumienie - nawet jakbyś chciał tak:

Już wyjaśniam. Skoro każdy wskaźnik zajmuje dwa bajty w pamięci, to wywnioskowałem, że jeżeli będe miał adres w zmiennej dwubajtowej, to wyjdzie jak bym użył operatora pobierania adresu. Przyznaje, że była to mała prowokacja :) , bo sprawdziłem czy zadziała takie wyrażenie w eclipse wcześniej. Zdziwiłem się, jak otrzymałem ostrzeżenia od kompilatora. Dlatego umieściłem takie ptaniue tutaj. Natomiast jak przeczytałem:
Cytuj:
Dobrze ci się wydaje ale zobacz jakie są ważne szczegóły - nie dokończyłeś tej definicji a to pokazuje że nie zaskoczyłeś co to są albo po co w ogóle deklaruje się TYPY wskaźników.

to poczułem jak bym dostał impuls na reset i wyskoczył z nieskończonej pętli :D No Ba! Przecież ważny jest typ danej na która wskaźnik wskazuje, aby odpowiednio dobrać adres. Dziękuje, to mi bardzo pomogło.

Tutaj popełniłem błąd przy pisaniu:
Kod:
tablica_adres[2] = @jakas_zmienna;

Miało być tak:
Kod:
tablica_adres[2] = &jakas_zmienna;

pozostałości z asemblera 8051...

No dobra, skoro tak pięknie Mirku naprowadziłeś na dobro drogę, mam kolejne pytanie.
Wspomniałem wcześniej, że moje oczy zrobiły się wielkie jak 5zl, jak zobaczyłem połączenie struktury ze wskaźnikami. Np.taką składnie:
Kod:
struct nazwa
{
   int pole1;
   float pole2;
   char pole3[20];
} Obj1, *PObj2;

W rozdziale na temat struktur jest pięknie opisane jak dostać się do każdej zmiennej w strukturze za pomocą kropki. Rozumiem, że przecinek za "Obj1" oznacza drugi egzemplarz takiej struktury (prawda?). Czy jest to samo jakbym użył instrukcji typedef, a następnie utworzył dwa egzemplarze takiej struktury? Natomiast w tym miejscu ta gwiazdka mnie przeraża, nawet nie wiem jak probować to odczytać. Nie daje mi też spokoju ta "nazwa" za definicją struktury.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 20:37 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Ja tam wolę porządek dlatego nigdy bym nie użył takiego zapisu jak pokazałeś tylko zrobił to tak:

Kod:
typedef struct {
  int pole1;
  float pole2;
  char pole3[20];
} TPOLE_INFO;


a potem ładnie:

Kod:
TPOLE_INFO Obj1;
TPOLE_INFO *PObj2;


i co ? teraz widać wyraźniej i lepiej dla oka co tu robię ? poza tym jeśli jedna struktura ma służyć do tworzenia różnych obiektów to po jakiego grzyba tworzyć to w kodzie jako zmienne globalne razem z definicją struktury, to się nazwya "misz-masz". Ale jak widać po przykładzie, który podałem wyżej o wiele przyjaźniej dla oka i dla całego programu ;) a od razu widać że powołuję strukturę o nazwie Obj1 typu TPOLE_INFO oraz wskaźnik do struktury *PObj2 o takim samym typie - jaśniej teraz ? ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 22:08 
Offline
Użytkownik

Dołączył(a): 01 cze 2012
Posty: 72
Lokalizacja: Gdańsk
Pomógł: 2

Nawet nie wiesz jak bardzo :D Sam się nie mogę nadziwić, jak sposób zapisu może utrudznić/ułatwić zrozumienie kodu.

Ta żeby było wszystko jasne i czy napewno to dobrze zrozumiałem.
To jest wskaźnik do struktury:
Kod:
TPOLE_INFO *PObj2;

I teraz, pobieram adres zmiennej w strukturze tak:
Kod:
PObj2 = &Obj1.pole1;

Korzystając ze wskaznika, pobieram dane do zmiennej:
Kod:
jakas_zmienna = *PObj2;

Jeżeli zwieksze zawartość wskaźnika o jeden:
Kod:
PObj2++;

To wskaźnik będzie wskazywał na drugą zmienną w strukturze? A przy kolejnym zwiekszeniu, na kolejną zmienną, pomimo, że są różnego typu?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 cze 2012, o 22:58 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Nie nie nie ;) teraz zamieszałeś troszkę ;)

tzn to masz dobrze:

Kod:
TPOLE_INFO *PObj2;


czyli to jest wskaźnik ale nie do struktury - tylko wskaźnik TYPU TPOLE_INFO a to chyba różnica prawda ? ;)

dopiero po takiej operacji:

Kod:
PObj2 = &Obj1;


można byłoby powiedzieć, że PObj2 jest wskaźnikiem do struktury Obj1 ;)

i oczywiście coś takiego nie miałoby sensu:

Kod:
PObj2 = &Obj1.pole1;


ponieważ do wskaźnika typu TPOLE_INFO chciałbyś przypisać adres (wskaźnik) jednej zmiennej z tej struktury i to typu int ;) więc sam widzisz, że to nie miałoby sensu.

A jeśli chcesz pobrać dane do zmiennej to nie tak:

Cytuj:
jakas_zmienna = *PObj2;


tylko np tak:

Cytuj:
int jakas_zmienna = *PObj2->pole1;


wtedy jakas_zmienna przyjmie wartość pole1 struktury Obj1, ponieważ posługujesz się wskaźnikiem PObj2 ;) do którego wcześniej przypisaliśmy adres tejże struktury. Zauważ, że jeśli działasz na wskaźniku to do pól struktury odwołujesz się nie po kropce a po takim czymś

->

a gdybyś chciał to samo zrobić bezpośrednio ze struktury Obj1 to wtedy z kropką:

Kod:
int jakas_zmienna = Obj1.pole1;


I w przypadku wskaźników na struktury zapomnij o PObj2++ bo to nie są tablice, a skoro PObj2 jest wskaźnikiem na strukturę to po tej operacji wskazywałby na kolejny bajt w pamięci RAM gdzie kończy się ta właśnie struktura ;) czyli w ciemność ;) No chyba żebyś zdefiniował tablicę struktur np tak:

Kod:
TPOLE_INFO Obj3[4];
TPOLE_INFO *wsk = Obj3;


wtedy oczywiście mógłbyś zrobić wsk++ i po tej operacji wskazywałby on na kolejny element tablicy Obj3, w której każdy jej element jest typu TPOLE_INFO.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 10 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 9 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO