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

Struktura i wskaznik

VPS Starter Arubacloud
0 głosów
257 wizyt
pytanie zadane 9 kwietnia 2018 w C i C++ przez lambdag Obywatel (1,310 p.)

Witam, chciałbym się upewnić czy dobrze myślę: mam taki pseudo kod:

struct node{
       int x;
       node *next;
}
void add(node *head){

}
int main()
{
    node *head = 0;
    add(head);
    return 0;
}

W takim sensie do funkcji add przesyłam nie orginalna strukturę tylko jej kopię?? Musiałbym dodać druga gwiazdkę lub referencje żeby to miało sens? Bo mógłbym zmienić funkcję żeby zwracała strukturę to wtedy miałoby to sens ale tak to nie? Dobrze to rozumiem..?

 

2 odpowiedzi

+1 głos
odpowiedź 9 kwietnia 2018 przez RafalS VIP (122,820 p.)
wybrane 9 kwietnia 2018 przez lambdag
 
Najlepsza

Nie. Działa to w ten sposób, że mając wskaźnik do struktury masz w pamięci dwa bloczki.
Wyobraź sobie to w ten sposób. Tworzysz sobie strukture typu node w normalny sposób: node n;. W tym momencie zostaje wydzielony blok w pamięci powiedzmy, że blok numer 69, w którym przechowywana jest ta struktura, wartość w tym bloku to int i node*, ich wartosci są losowe przed inicjalizacją. Teraz tworzysz wskaźnik do node:  node* wsk;. Rezerwujesz kolejny blok w pamięci na wskaźnik do node, powiedzmy, że pod adresem 80, wartość tego bloku jest randomowa, w momencie inicjalizacji sa tam jakieś smieci. I teraz chcesz, żeby ta zmienna (blok w pamięci) wskazywała Ci na twoją wcześniej utworzoną strukture (pamiętała adres w pamięci gdzie trzymana jest ta struktura). Robisz więc wsk = &n;. I wtedy wartość wsk wynosi 69. Gwiazdkując (dereferencując) ten wskaźnik trafiasz do twojej strukturki n. Jeśli zrozumiałeś ten wywód to będziesz już w stanie sam odpowiedzieć na pytanie co jest przekazywane do funkcji. Musisz jeszcze pamiętać, że argumenty funkcji są przekazywane przez wartość:

void fun(int x) { x = 100;}
int main(){
int a = 0;
fun(a); // a wciaz wynosi 0 bo funkcja pracuje na kopii zmiennej a
}

Wygląda to tak:

Bloki pamięci to kwadraty, w środku jest wartość, u góry nazwa zmiennej.

Nie wiem czy to widzisz, ale zmodyfikowałeś wartość innej zmiennej niż a, wartość innego bloku pamięci.

Na pewno widziałeś też taki kod:

void fun(int* x) {*x=100;}
int main(){
int a = 0;
int* wskaznik_na_a = &a;
fun(wskaznik_na_a); // wartosc a zmienia się
}

Tutaj też argument przekazywany jest przez wartość, ale tym razem wartość wskaźnika, a nie inta. Wrzucasz sobie inta do bloku pamięci o numerze 65 i przesyłasz wskaźnik do tego bloku. Dostajesz więc taką sytuacje:

Tym razem możesz modyfikować wartość a, bo masz dostęp do bloku pamięci, w którym jest nasza zmienna a.

A co jeśli będzie trzeba zmienić wartość samego wskaźnika, a nie wartość bloku na który ten wskaźnik pokazuje, jeśli zrobisz tak jak w pierwszym przypadku:

void fun(int* wsk){ wsk = 0;}

To dostaniesz coś takiego

Po wyjściu z funkcji zmienna kopia wsk znika, nie zmieniłeś więc wartości wskaźnika wsk. Idąc podobną logiką jak wcześniej, wystarczy, że dodasz gwiazdke i bedzie cacy:
 

void fun(int** wsk){ *wsk = 0;}

Teraz po wyjściu z funkcji wartość samego wskaźnika zmieni się, bo modyfikujesz blok pamięci w którym trzymana jest jego wartość.

 

 

Po krótkim wstępie wracając do Twojego przykładu: po pierwsze to nie jest pseudokod tylko C / C++ :P.
Całe to zamieszanie można rozwiązać korzystając z referencji, które są dostępne w C++, w C nie. Referencje to tak jakby druga nazwa na tą samą zmienną (ten sam blok w pamięci), wtedy możesz modyfikować jej wartość normalnie:

void fun(int& x){x=100;}

i wartość zmiennej przesłanej do funkcji zmieni się po wywołaniu funkcji.

A jeśli chodzi o wskaźniki, to jeśli nie rozumiesz tego co próbowałem wyjaśnić to musisz pamiętać jedynie tyle, że jeśli chcesz zmodyfikować argument to musi to wyglądać w ten sposób:
chcesz zmodyfikować inta to musisz przeslać int* wsk i zmodyfikować *wsk. Chcesz zmienić sam wskaźnik to musisz przesłać int** i podobnie zmodyfikować *wsk itd z dowolną ilością gwiazdek.

Mam nadzieję, że cokolwiek rozjaśniłem.

komentarz 9 kwietnia 2018 przez lambdag Obywatel (1,310 p.)
Dobrze wyjaśniłeś wlasnie o to mi chodziło chyba źle wyslowilem w pytaniu :D
+1 głos
odpowiedź 9 kwietnia 2018 przez Bondrusiek Maniak (61,370 p.)

Witam,

używając wskaźnika jako argument funkcji można przesłać oryginalną strukturę. Przykład w C++

#include <iostream>

using namespace std;

struct node{
       int x;
       node *next;
};

void add(node *head){
    cout << "x " << head->x << endl;
    head->x += 1;
}

int main()
{
    node *head;
    head = new node();
    head->x = 1;
    add(head);
    add(head);
    delete head;
    return 0;
}

 

Podobne pytania

0 głosów
2 odpowiedzi 654 wizyt
pytanie zadane 10 sierpnia 2018 w SQL, bazy danych przez mi-20 Stary wyjadacz (13,190 p.)
0 głosów
1 odpowiedź 568 wizyt
pytanie zadane 11 czerwca 2018 w SQL, bazy danych przez emeryt68 Nowicjusz (130 p.)
0 głosów
1 odpowiedź 161 wizyt

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...