• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wskaźniki - kilka pytań

Object Storage Arubacloud
+3 głosów
886 wizyt
pytanie zadane 23 sierpnia 2015 w C i C++ przez Patrycjerz Mędrzec (192,320 p.)

Witam Drogą Społeczność,

wskaźniki oczywiście znam. Pytania będą miały bardziej związek z ich ogólnymi założeniami. Więc:

  • Czy adres danej zmiennej jest generowany przez system, jeśli poprosimy o niego operatorem &? (przecież jeśli mamy np. wskaźnik na wskaźnik, to jego adres nie jest przetrzymywany ciągle w pamięci, co nie?)
  • Jak długi może być taki ciąg: wskaźnik na wskaźnik na wskaźnik...? Czy to tylko zależy od pojemności pamięci komputera?

I pytanie z innej beczki:

  • Czy nazwa zmiennej w danym kodzie programu jest lokalnym wskaźnikiem na dane, które przechowuje? Jak to widzi system? 

To chyba wszystko. Pytania zadane bardziej z chęci lepszego poznania działania komputera, bo nie samym programowaniem człowiek żyje laugh

Za wszystkie odpowiedzi będę bardzo wdzięczny. Pozdrawiam! 

3 odpowiedzi

+5 głosów
odpowiedź 24 sierpnia 2015 przez hit02 Nałogowiec (33,970 p.)
wybrane 24 sierpnia 2015 przez Patrycjerz
 
Najlepsza

Witam.

W pierwszym pytaniu po części masz rację, a po części nie. Zmienna ma odrazu swój adres w pamięci, a operator & tylko daje ci do dostęp do wartości tego adresu. Prawda jest taka, że kompilator miejsca odwołań do pamięci wstawi odwołania do adresów używając wskaźników, ale nie muszą to być odwołania absolutne. Procesor (x86) zazwyczaj obsługuje odwoływania się do pamięci względem czegoś, a odwołanie absolutne (pod konkretny adres) jest tylko szczególnym przypadkiem. Po dokładniejszy opis możliwych odwołań patrz Pierwszy Tom Dokumentacji Intela rozdział "Specifying an Offset" (3.7.5). Tam, gdzie w kodzie masz operator &, tam kompilator poprostu wstawi obliczony adres, przez który odwoływał by się do zmiennej.  Zauważ też, że wyrażenie

something = &&var;

 nie ma sensu.

Jednak to system zarządza pamięcią i to on może ci przydzielic pięc pod konkretnym adresem, więc w tym sensie adres jest generowany przez system.


Ciąg wskaźnik->wskaźnik->wskaźnik->... może być długi na tyle, ile masz pamięci dzielone przez rozmiar wskaźnika. (4 bajty na 32 bit, 8 na 64 bit) Aczkolwiek adwoływanie się przez więcej niż jeden wskaźnik zajmuje więcej czasu, bo tylko pojedyńcze odwołanie można zakodować w kodzie maszynowym i wypełnienie całej pamięci takimi odwołaniami nie miało by większego sensu, bo nie starczyło by miejsca na to, do czego mają się one ostatecznie odwołać. cheeky A z resztą i tak nie wypełnisz całej pamięci, ze względu na to, że nie każdą komórkę pamięci wirtualnej system może ci przydzielić, a część jest też w stylu nietykalnego readonly (na pewno na Windows).


Tak. Nazwa jest lokalnym wskaźnikiem z tą róznicą, że np. w C nie możesz mieć takiego wskaźnika, jaki by był na zmienną lokalną, to znaczy w assembly

[EBP - 8]

 będzie (zazwyczaj) odwołaniem do zmiennej lokalnej. (Nawiasy kwadratowe oznaczają odwołanie do pamięci, a rejestr EBP zazwyczaj wskazuje na strukturę zwaną ramką stosu).

Natomiast system tego nie widzi. System co najwyżej łapie wyjątki, które mu procesor po takim odwołaniu rzuci. System natomiast zarządza pewnymi strukturami, które określają, które adresy w pamięci wirtualnej będą prowadzić do których adresów w pamięci fizycznej. Zazwyczaj system może to określać oddzielnie dla grup po 4096 bajtów.

 

komentarz 24 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)

Dzięki za wyczerpującą odpowiedź. Czyli to znaczy, że danych w pamięci jest więcej o te ilość komórek * 4 / 8 bajtów. Sądziłem, że adresy są generowane tylko przy zapotrzebowaniu na nie. Z tego wynika, że pamięć to pary komórek na dane + komórki na adres.

komentarz 24 sierpnia 2015 przez hit02 Nałogowiec (33,970 p.)

Zależy jak na to spojżeć. System dzięki mechanizmowi zarządzania pamięcią mówi procesorowi, kiedy rzucić wyjątkiem, a kiedy nie. Dzięki temu może on powiedzieć, które strony pamięci wirtualnej są prawidłowe, a które nie. Na przykład pamięć od adresu 0, do 0x1000 w więkrzości przypadków nie jest zaalokowana, bo jest tam tzw. NULL page, na którą wskazuje NULL pointer.

Pamięci rzeczywistej masz zawsze tyle, jak dużo sobie kupisz w sklepie, ale system może np. pewne odwołania skierować do innej pamięci np. dysku twardego dzięki temu, że dostanie wyjątek z informacją o niepowodzeniu odwołania do strony w RAM. Dzięki temu program na 32 bitowej maszynie ma zawsze nieco mniej niż 2 GB dla siebie. Pozostałe 2 GB system zabiera dla siebie. smiley

Natomiast to, że wskaźnik ma te 4/8 bajtów nie ma nic wspólnego z ilością pamięci poza tym, że musi on być w stanie objąć dowolny adres w pamięci. Z tąd taki, a nie inny rozmiar.

Co do tych komórek na dane + komórek na adres, to tak. Jest to prawda, ale są one chaotycznie wymieszane tj. wskaźnik jest zwykłą daną i siedzi razem ze zmiennymi. Ewentualnie może on być wyliczony w czasie kompilacji i umieszczony bezpośrednio w kodzie razem ze stałymi. Pamięć nie ma rozróżnienia między nimi, natomiast procesor może sobie wziąść dowolną wartość i się odwołać korzystając z niej jak ze wskaźnika. Interpretacja zależy od kodu maszynowego, czyli od programisty i kompilatora.

0 głosów
odpowiedź 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)
Wskaźnik nie jest generowany przez system tylko system odczytuje indeks po jakim zmienna się znajduje w pamięci RAM. Wskaźnik jest zwykłą zmienną z tym, że przechowuje adres więc skoro jest zmienną to i sam ma adres.

Wskaźnik do wskaźnika ... itd może się ciągnąć w nieskończoność bo deklaracja i tak tylko jedno miejsce(8B) rezerwuje. Operator & zwraca adres czyli defakto wskaźnik na daną zmienną.

Nazwa na pewno nie jest "lokalnym wskaźnikiem" bo byłoby możliwe napisać int a = 5; int* wsk = a; System nijak tego nie widzi. "Widzi" to kompilator który generuje odpowiedni kod maszynowy do wykonania przez procesor, który to już zawiera konkretne adresy w pamięci a nie nazwy zmiennych.

Jeśli się cokolwiek nie zgadza to piszcie w komentarzach, ale tak to wykładowca tłumaczył.
komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)
Z pierwszym punktem się nie zgodzę. Jak już mówiłem, np. adres wskaźnika na wskaźnik nie jest ciągle zapisany w pamięci, ponieważ praktycznie zapchałoby to cały RAM. Z tego też względu to chyba system generuje adres danej zmiennej (wskaźnika) podczas chęci pobrania go.
komentarz 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)
Chyba mamy inne rozumienie słowa generuje. Dla mnie generować może na przykład losowo i wychodziłyby bzdury. Adres jest odczytywany z pamięci. Jeżeli potrzebujesz wskaźnika na wskaźnik na wskaźnik na wskaźnik na cośtam to taka zmienna(wskaźnik "stopnia" jeden mniej) rzeczyswiście musi istnieć lub też powstać, żeby sensownym było używanie takiego wskaźnika i nie instnieje takie coś jak adres adresu, adresy mogą mieć tylko zmienne, więc jeżeli chcesz ten dziesiąty wskaźnik na inta to te dziesięć wskaźników musi istnieć rzeby się jakoś do tego inta dostać.
komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)

Jeśli mamy te dziesięć wskaźników, to chyba system (jeśli odniesiemy się do nich pierwszy raz w jednym momencie) stworzy je w tym samym czasie. Nie chcę tym pytaniem dogryzać komuś, tylko chciałbym otrzymać odpowiedź od jakiegoś specjalisty, który powie mi jasno, że tak, lub nie. Oczywiście dzięki, że próbujesz mi pomóc. A generowanie to tworzenie (ja znam taką definicję tego słowa) wink

komentarz 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)

Zgodze się z tą definicją z tym że nie w każdym wypadku, np. właśnie w programowaniu przy deklaracji tworzymy sobie zmienną i ona ma jakieś konkretne miejsce w pamięci ale go nie generujemy bo w tedy moglibyśmy sobie wygenerować nieskończoną ilość pamięci RAM tylko jakieś jedno miejsce jest przydzielane.

Ale wracając do pytania to standard C mówi, że kompilator musi być w stanie skompilować kod z conajmniej wskaźnikiem 12 stopnia czyli jak już masz 20 wskaźników to jakiś słaby kompilator może nie puścić i wywalić error

fatal error C1026: parser stack overflow, program too complex

oczywiśnie niektóre mogą wspierać do kilku\nastu tysięcy. Tu kończy się moja wiedza na ten temat.

komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)

Sorki, ale pierwszego akapitu prawie w ogóle nie rozumiem - m.in. przez te "generowanie pamięci RAM" wink Co do drugiego, to myślałem, że jedynym ograniczeniem tego jest pojemność pamięci, ale dzięki za informację.

komentarz 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)
z tym generowaniem to chodzi o to, że przy deklaracji przydzielemy adres a nie generujemy bo adres sobie gdześ tam w kości siedzi i nie tworzymy nowego, może rzeczywiście troche to zagmatwane ale tak wygląda mój tok myślenia dopuki nie zrefraktoryzuje tego co chcę napisać.
komentarz 23 sierpnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)
edycja 23 sierpnia 2015 przez MrWeb

Lekkie sprostowanie:

Wskaźnik do wskaźnika ... itd może się ciągnąć w nieskończoność bo deklaracja i tak tylko jedno miejsce(8B) rezerwuje. Operator & zwraca adres czyli defakto wskaźnik na daną zmienną.

Wskaźnik, to zmienna która musi utrzymać w sobie adres innej zmiennej, czyli na systemach x64 zajmuje 8 bajtów, na x32 zajmuje 4 bajty.

2^32 = 4294967296 bajtów, czyli 32bitowy system może maksymalnie zaadresować (użyć) 4096 MB pamięci RAM.

Największa zmienna dla komputera 32 bitowego to zmienna zawierająca 32 bity ;)

Większe zmienne to tak naprawdę połączenie mniejszych, 32 bitowych zmiennych.

Dlatego wskaźniki mają rozmiar uzależniony od architektury procesora.

 


I odpowiedź na pierwsze pytanie - 

Czy adres danej zmiennej jest generowany przez system, jeśli poprosimy o niego operatorem &? (przecież jeśli mamy np. wskaźnik na wskaźnik, to jego adres nie jest przetrzymywany ciągle w pamięci, co nie?)

 Właśnie, że jest! Dla procesora nie istnieje coś takiego jak nazwa zmiennej, liczy się tylko adres i wartość pod tym adresem.

Każda zmienna to "szufladka". 

Każda "szufladka" ma swój adres i swoją wartość

Komputer odwołuje się do tych wartości na podstawie adresu szufladki.

Więc gdy chcesz uzyskać adres zmiennej operatorem &, to komputer tak naprawdę jedyne co zrobi, to przeczyta adres szufladki, a nie jej zawartość.

komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)

@MrWeb Oczywiście, ale czy w pamięci jest już zdefiniowany adres wskaźnika do wskaźnika do wskaźnika do wskaźnika... do zmiennej? Wg mnie jest on generowany w trakcie poproszenia o niego przez program.

komentarz 23 sierpnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)
Ah, chodzi Ci o to, skąd procesor wie, do której komórki się odwołać, tak?

Np, skąd procesor wie, że twoja zmienna do której chcesz się odwołać ma teraz taki adres, a nie inny.

Jeśli tak, to odpowiedzią jest hasło "wirtualna przestrzeń adresowa".

https://pl.wikipedia.org/wiki/Przestrze%C5%84_adresowa

i po angielsku, z większym opisem - https://en.wikipedia.org/wiki/Virtual_address_space

System operacyjny decyduje, jakie adresy *tym razem* ma nadać zmiennym w twoim programie tworząc taką "tablicę" adresów dla danego programu.

Operator & tak naprawdę nie zwraca adresu fizycznej komórki pamięci RAM, tylko zwraca adres który dostał od systemu operacyjnego.
komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)
O, bardzo dziękuję za tę odpowiedź. Czyli dobrze mówiłem, że to wszystko nie jest stałe...
0 głosów
odpowiedź 23 sierpnia 2015 przez Dorion300 Szeryf (90,250 p.)
  • Czy nazwa zmiennej w danym kodzie programu jest lokalnym wskaźnikiem na dane, które przechowuje? Jak to widzi system? 

Nie do końca rozumiem ale powiem to tak:

jest sobie program.

Rezerwuje sobie pamięc odtąd dotąd.

Adres np. 0xf4ad będzie miejscem gdzie zaczyna się np. Obiekt A klasy C, i jeśli za każdym razem ta zmienna A zostanie użyta to zamiast tego A jest po prostu adres wpisywany.

Wskażnik jest zwykła zmienną przechowującą adres.

Czyli jeśli stworzymy taki o to wskażnik to tak naprawdę tworzymy mała zmienną która jedynie może adres.

komentarz 23 sierpnia 2015 przez Patrycjerz Mędrzec (192,320 p.)
Że wskaźnik jest także zmienną, to wiem. Chodziło mi bardziej, jak to interpretuje kompilator i obsługuje system. Zapewne jest to jakby wskaźnik, bo możesz z tej nazwy korzystać wielokrotnie, a program wie, o co ci chodzi.

Podobne pytania

0 głosów
2 odpowiedzi 339 wizyt
pytanie zadane 5 września 2015 w C i C++ przez mrcnsct Nałogowiec (36,390 p.)
0 głosów
1 odpowiedź 298 wizyt
pytanie zadane 4 października 2016 w C i C++ przez Kuba321 Użytkownik (730 p.)
+4 głosów
2 odpowiedzi 386 wizyt
pytanie zadane 2 stycznia 2016 w C i C++ przez obx88 Nowicjusz (160 p.)

92,634 zapytań

141,505 odpowiedzi

319,883 komentarzy

62,015 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...