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

Adresy tablic w c++

Object Storage Arubacloud
0 głosów
1,269 wizyt
pytanie zadane 30 grudnia 2017 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)

Witam, zaznaczam że ostatnio zadałem podobne pytanie, jednak usłyszałem tylko że dzisiaj już nie ma potrzeby stosowania takich zawiłych instrukcji wskaźnikowych. Zgadzam się z tym oczywiście, jednak ucząc się c++ z książki "C++ Szkoła Programowania" miał bym czystsze sumienie gdybym wszystko tam w pełni zrozumiał (nawet wskaźniki). Trochę już sam doszedłem do podanego tam przykładu ale mam kilka pytań:
 

int *arr[10]; //jakaś  tablica 
int (*wsk)[10] = &tell; //w miarę zrozumiałe

nie jestem pewny czy dobrze rozumiem tą konstrukcje. *wsk jest w nawiasie żeby nie zostało to zinterpretowane jako tablica wskaźników. Jak to można teraz nazwać (opisać). Wskaźnik wskazujący na całą tablicę czy jak?

cout << (*pas)[4] << endl; //pokazywanie wartości jakiejś szufladki *pas w nawiasie dlaczego? Sprawdzałem bez nawiasu i też działa 
cout << (pas)[4] << endl; //tym razem adres 
cout << pas+4 << endl; //dostajemy się na element o nr 4 (widać jego adres)
cout << *pas+4 <<endl; //chciałem zobaczyć wartość korzystając z metody wskaźnikowej (ale dalej adres)

Wszystko jest tu opisane co mam na myśli. Oczywiście jak tym razem nie uzyskam odpowiedzi to nie będę więcej razy udostępniał tego pytania :), jakoś przeboleje że czegoś nie zrozumiałem. Z góry dziękuje za pomoc i pozdrawiam wink

2
komentarz 30 grudnia 2017 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Dlatego ja wolę stosować taki zapis:

int* nazwa

Niż taki:

int *nazwa

Chociaż w pewnym przypadku może być to mylące:

int* a, b;

Zmienna a będzie wskaźnikiem na int, natomiast zmienna b będzie intem.

2 odpowiedzi

+1 głos
odpowiedź 30 grudnia 2017 przez j23 Mędrzec (194,920 p.)
wybrane 30 grudnia 2017 przez Jakub 0
 
Najlepsza

cout << (*pas)[4] << endl; //pokazywanie wartości jakiejś szufladki *pas w nawiasie dlaczego? Sprawdzałem bez nawiasu i też działa

Działać będzie, ale znaczenie jest inne. Z nawiasami dobierasz się do piątego elementu tablicy wskazywanej przez pas.  Bez nawiasów - do pierwszego elementu piątej tablicy. Operator [] ma wyższy priorytet od operatora wyłuskania *.

cout << pas+4 << endl; //dostajemy się na element o nr 4 (widać jego adres)

Nie element, a tablicę o indeksie 4 ;)

cout << *pas+4 <<endl; //chciałem zobaczyć wartość korzystając z metody wskaźnikowej (ale dalej adres)

* ma wyższy priorytet, więc *pas zwraca wskaźnik na pierwszy element tablicy wskazywanej przez ten wskaźnik. Zatem cout wyświetli adres komórki o indeksie 4.

komentarz 30 grudnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
edycja 30 grudnia 2017 przez Jakub 0

Dziękuje bardzo, ale mam kilka wątpliwości:

Działać będzie, ale znaczenie jest inne. Z nawiasami dobierasz się do piątego elementu tablicy wskazywanej przez pas.  Bez nawiasów - do pierwszego elementu piątej tablicy. Operator [] ma wyższy priorytet od operatora wyłuskania *.

 Nie rozumiem tylko tego zdania: " do pierwszego elementu piątej tablicy". jakiej piątej tablicy? Dla mnie tablica to coś zbiór elementów ułożonych liniowo. np: int tab[10] a tab[0] to nie tablica zerowa tylko indeks zerowy tablicy tab (element). Ale nie wiem, pierwszy raz słyszę takie nazewnictwo.

* ma wyższy priorytet, więc *pas zwraca wskaźnik na pierwszy element tablicy wskazywanej przez ten wskaźnik. Zatem cout wyświetli adres komórki o indeksie 4.

 

Skoro * ma wyższy priorytet  to *pas+4  nie powinno oznaczać dodanie 4 do pierwszego elementu tablicy (indeksu 0)?

 

Przepraszam że nic nie rozumiem crying. Nie wiem co się ze mną dzieje

 

1
komentarz 30 grudnia 2017 przez j23 Mędrzec (194,920 p.)

Nie rozumiem tylko tego zdania: " do pierwszego elementu piątej tablicy". jakiej piątej tablicy?

pas jest wskaźnikiem na wartość typu short[10], więc jak dasz *pas[4], to tak jakbyś zrobił *(pas + 4) lub pas[4][0] (czyli pierwszy element (o indeksie 0) piątej tablicy short[10] (o indeksie 4)).

 

W swoim przykładzie czytasz poza dozwolonym zakresem, i gdyby nie to, że przypisałeś tam niewielką tablicę lokalną rezydującą na stosie, bardzo prawdopodobne dostałbyś błąd dostępu do pamięci.

 

 

Skoro * ma wyższy priorytet  to *pas+4  nie powinno oznaczać dodanie 4 do pierwszego elementu tablicy (indeksu 0)?

No, dokładnie to robi, przecież to napisałem ;) Tylko zastanów się, jakiego typu jest ten pierwszy element.

 

komentarz 30 grudnia 2017 przez Jakub 0 Pasjonat (23,120 p.)

Dzięki wielki za tłumaczenie mi tego, ale mówię szczerze że cały czas nie rozumiem tego pojęcia że n-ta tablica, jeszcze bardziej rozwaliło moje spojrzenie na temat to zdanie:
 

pas[4][0] (czyli pierwszy element (o indeksie 0) piątej tablicy short[10] (o indeksie 4)).

Cały czas ta piąta tablica i któryś jej element, czy to ma coś wspólnego z tablicami dwu wymiarowymi? Nie chodzi mi o to żebyś mi jeszcze raz tłumaczył jak to jest z nawiasem, bez nawiasu itd. Myślę że to pojmę kiedy poprawnie zrozumiem co właściwie robi ten zapis:

int (*wsk)[10] = &tell;

Myślałem że jest to po prostu wskaźnik który ma wskazywać adres dziesięcio elementowej tablicy. Oczywiście w nawiasie by to nie była zwykła tablica wskaźników. Ty jednak mówisz że jest kilka tablic: czyli pierwszy element (o indeksie 0) piątej tablicy. Całe moje nie zrozumienie wynika właśnie chyba  z tego że  chyba kompletnie źle rozumiem działanie tej instrukcji.

Skoro * ma wyższy priorytet  to *pas+4  nie powinno oznaczać dodanie 4 do pierwszego elementu tablicy (indeksu 0)?

No, dokładnie to robi, przecież to napisałem ;) Tylko zastanów się, jakiego typu jest ten pierwszy element.

Dla mnie skoro samo pas to adres zerowego indeksu  to * pas to jego wartość (bo użyte wyłuskiwanie). *pas+4 to dodanie do pas 16 bajtów (bo + 4 a int ma 4 bajty więc 4*4 = 16). Wobec czego zapis jest równoważny zapisowi pas[4]. Potem wykonujemy wyłuskiwanie wartości i powinna się ukazać 'wyłuskana' wartość spod pas[4].  Źle to rozumiem chyba też dlatego że nie zrozumiałem tej ( int (*wsk)[10] = &tell;  ) instrukcji. Tak jak mówię gdybyś tylko mógł powiedzieć co ona właściwie robi.

 

Pewnie łapiesz się teraz za czoło co ja teraz znowu nie rozumiem...

1
komentarz 30 grudnia 2017 przez j23 Mędrzec (194,920 p.)

czy to ma coś wspólnego z tablicami dwu wymiarowymi?

Tak. To ma taki związek z tablicami dwuwymiarowymi, jak zwykły wskaźnik z tablicą jednowymiarową.

size_t n = 20;

short (*wsk)[10] = new short[n][10];

 

Myślałem że jest to po prostu wskaźnik który ma wskazywać adres dziesięcio elementowej tablicy.

Nie myl wskaźnika na pierwszy element tablicy ze wskaźnikiem na tablicę. To dwa różne wskaźniki, choć zawierają ten sam adres. Tak zapis: short* p = wsk; nie przejdzie, bo wsk wskazuje na wartość typu short[10] a nie short. Dopiero jak wyłuskasz wskaźnik, będziesz mógł przypisać adres: short* p = *wsk;

 

Pewnie łapiesz się teraz za czoło co ja teraz znowu nie rozumiem...

Pisałem Ci, że arytmetyka wskaźnikowa potrafi być zawiła ;)

komentarz 30 grudnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
Miałeś racje że jest zawiła :) Ale już to bardziej pojmuje, problem był po prostu takli że źle wyobrażałem sobie działanie tej deklaracji. W książce moim zdaniem jest to bardzo krótko wytłumaczone. Chyba że chodziło tam tylko o to żeby podać jakąś ciekawostkę. Teraz sobie jakoś to wszystko rozpracuje. Dzięki za pomoc i pozdrawiam
0 głosów
odpowiedź 30 grudnia 2017 przez obl Maniak (51,280 p.)

To:

int *arg[10];

jest wskaźnik na 10-cio elementową tablicę wskaźników *int.

To:

int (*wsk)[10] = &tell;

jest wskaźnik na tablicę 10-cio elementową tablicę int-ów. Może taki kod będzie lepszym wyjaśnieniem:

int t[10];
int (*wsk)[10] = &t;

for(int* index = t; index < t + 10; index++){
	*index = (int)(index - t);
}

for(int* index = *wsk; index < *wsk + 10; index++){
	std::cout << *index << std::endl;
}

std::cout << typeid(wsk).name();

 

komentarz 30 grudnia 2017 przez Jakub 0 Pasjonat (23,120 p.)

Trochę nie rozumiem:

int *arg[10];

jest wskaźnik na 10-cio elementową tablicę wskaźników *int.

To nie jest po prostu tablica wskaźników!? Takie nazwanie tego bardzo mnie zdziwiło, ja myślałem że to się np tak używa:

int x, y, z;
int *arg[3];

arg[0] = new int ;s
arg[1] = &y;
//itd...

Ale mogę się mylić :X

1
komentarz 31 grudnia 2017 przez obl Maniak (51,280 p.)
Sorry pomyliłem się tak to jest tablica wskaźników.
komentarz 31 grudnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
Ulżyło mi ;)

Podobne pytania

0 głosów
1 odpowiedź 148 wizyt
pytanie zadane 4 marca 2020 w C i C++ przez kolijk Użytkownik (600 p.)
0 głosów
1 odpowiedź 914 wizyt
pytanie zadane 2 listopada 2017 w C i C++ przez Kamil Duljas Użytkownik (990 p.)
–2 głosów
0 odpowiedzi 447 wizyt
pytanie zadane 10 czerwca 2018 w C i C++ przez Jajestem Użytkownik (670 p.)

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 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!

...