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

wskaznik na wskaznik_dynamiczna alokacja pamieci

VPS Starter Arubacloud
0 głosów
141 wizyt
pytanie zadane 8 czerwca 2020 w C i C++ przez reken Początkujący (390 p.)

Wtam
Pisze w sprawie bardzo czesto pojawiajacej sie chyba na forach chodzi o wskazniki na wskaznik i dynamiczna alokacja pamieci w polaczeniu przejrzalem juz sporo mat ale gdzies tego nie kumam.
Mam do wykonania program  który pobierze od użytkownika dany rozmiar tablicy, a następnie wykorzystując przygotowaną funkcję zarezerwuje pamięć na tablicę i pobierze od użytkownika dana liczbę danych.
prototyp : 
 

int stworz(int **wsk, int N);

i teraz gdybym mial *wsk zamiast **wsk to zrobilbym to
 

wsk=malloc(N*sizeof(*wsk))

natomiast teraz jak mam wskaznik na wskaznik to nie bardzo wiem jak.Teroretycznie powinienem zadeklarowac 

 wsk=malloc(N* sizeof(*wsk));
    for(int i=0;i<N;i++){
        *(wsk+i) = malloc(sizeof(int));
    }

tylko przeciez ja dostane tablice jednowymiarowa jak uzytkownik mi poda np 10 liczb to jak zadeklarowac dla kazdej tablicy kolejna tablice?Bo z tego co zrozumialem jesli chodzi o wskazniki na wskaznik to jesli bym mial tab[5][3] to

wsk=malloc(5* sizeof(*wsk));
    for(int i=0;i<N;i++){
        *(wsk+i) = malloc(3*sizeof(int));
    }

I druga sprawa jesli chodzi o operowanie wskaznikami na wskazniki i rozumienie tematu bo nie lape
jak mialbym pojedynczy wskaznik np *(wsk+1) to najpierw przesunie wskaznik a potem operator wyluskania pobierze wartosc gdybym zrobil tak   *wsk+1  to najpierw pobierze wartosc z adresu ktory przechowuje wskaznik a potem doda 1 bo operator wyluskania ma wyzszy priorytet.To jak dziala to,( pobrane z innego forum)

1.   //przyklad:
2.   char tab[2][10]; //2 napisy 10cio znakowe
3.   char** tabptr = tab;
4.   
5.   **tabptr          //pierwszy znak pierwszego napisu
6.   **(tabptr+1)      //pierwszy znak drugiego napisu
7.   *(*tabptr+1)      //drugi znak pierwszego napisu
8.   *(*(tabptr+1)+1)  //drugi znak drugiego napisu

chodzi mi glownie o linijke 8 i zapis *(*(tabptr+1)+1).Przeciez  *(tabptr+1) wskaznik jest  przesuwany i pobierana wartosc no i ok ale potem jest dodawana wartosc +1 to przeciez powinno to byc dzialanie arytmetyczne a tutaj ten wskaznik jest przesuwany?To sprzeczne z tym o co chodzilo przy wskaznikach pojedynczych


I jesli bym chcial teraz cos zapisac do tej komorki uzywajac scanf to zapis np **tabptr bedzie taki &(**tabptr)  albo *(*(tabptr+1)+1)  lub  &(*(*(tabptr+1)+1)) ??W zasadzie to juz jest wskaznik ale nie wiem...
Bylbym bardzo wdzieczny gdyby ktos cos pojasnil bo juz siedze nad tym i cos nie moge zalapac ...

1 odpowiedź

0 głosów
odpowiedź 9 czerwca 2020 przez j23 Mędrzec (195,220 p.)
wybrane 10 czerwca 2020 przez reken
 
Najlepsza

i teraz gdybym mial *wsk zamiast **wsk to zrobilbym to
    
 

wsk=malloc(N*sizeof(*wsk))

Nowa pamięć byłaby widoczna jedynie w funkcji, a ona przecież ma przydzielić pamięć "na zewnątrz", dlatego masz podwójny wskaźnik. Tak powinno być:

*wsk = malloc(N * sizeof(int));

 

a tutaj ten wskaznik jest przesuwany?

Tak, bo wartością jest inny wskaźnik (tablica jest dwuwymiarowa). Pierwsze wyłuskanie dotyczy wiersza (jego adresu), drugie - elementu/wartości w wierszu.

komentarz 9 czerwca 2020 przez reken Początkujący (390 p.)

Ok ,dzieki wielkie a ja sie tyle glowilem po co jest podwojny wskaznik masz racje jakbym uzyl samego wsk nie uzyskalbym tego efektu.Mam jeszcze pytanie:
1.W zwiazku z tym napisalem cos takiego:

#include <stdio.h>
#include <stdlib.h>

int create_array_int(int **ptr, int N){
    if(N<=0)
        return 1;
    *ptr=malloc(N* sizeof(int));
    if(*ptr==NULL)
        return 2;
    return 0;
}


int main() {
    int size=0,answer=0;
    int **wsk=NULL;
    printf("Podaj rozmiar tablicy:");

    if((scanf("%d",&size))!=1){
        printf("Incorrect input");
        return 1;
    }
    else if(size<=0){
        printf("Incorrect input data");
        return 2;
    }
    answer=create_array_int(wsk,size);
    if(answer==2){
        printf("Failed to allocate memory");
        return 8;
    }
    printf("Podaj liczby:");
    for(int i=0; i<size;i++){
        scanf("%d",(*(*(wsk)+i)));
    }
    return 0;
}

Natomiast przy tym program zacina sie

Process finished with exit code -1073741819 (0xC0000005)

w ogole na funkcji ma problem.Wiem ze jeszcze musze zwolnic pamiec ale do tego ma byc oddzielna funkcja natomiast narazie probuje zalokowac porzadnie pamiec na ten wskaznik.Co jest niepoprawne ze go laguje

2.Czyli w tym przypadku wskaznika na wskaznik jezeli chce zmienic komorke pamieci na kolejna to uzywam
**(wsk+i)
jak rozumiem, no dobra a jak chce zapisac przy pomocy scanf to uzywam &(**(wsk+i))??
Przy pojedynczym wskazniku mam *wsk wartosc wyluskana , a samo wsk-adres komorki  wiec w przypadku wyzej tj **(wsk+i) musialbym zapisac to z jedna gwiazdka ??
scanf("%d", *(wsk+i));    ??

komentarz 10 czerwca 2020 przez j23 Mędrzec (195,220 p.)
int **wsk = NULL;

answer = create_array_int(wsk, size);

Funkcja oczekuje adresu na zmienną wskaźnikową, do której ma wpisać adres przydzielonej pamięci. Podałeś jej NULLa, dlatego program się wysypuje. Tak powinno być:

int *wsk;

answer = create_array_int(&wsk, size);

 

 for(int i=0; i<size;i++){
        scanf("%d",(*(*(wsk)+i)));

create_array_int, jak sama nazwa wskazuje, tworzy tablicę intów, jednowymiarową tablicę. Ten zapis jest nieprawidłowy. W tym przypadku wystarczy samo wsk + i (scanf oczekuje adresu zmiennej, do której ma wpisać pobraną wartość).

komentarz 10 czerwca 2020 przez reken Początkujący (390 p.)

Ok dzieki za odpowiedz juz zaplusowana.
To w zwiazku z tym mam jeszcze pytann kilka.

1.To teraz troche mnie to zdziwilo bo jezeli ja uzyje &wsk
 

create_array_int(&wsk, size);

to przekazuje adres wskaznika do fukcji.Jezeli ja mam

printf("%p",&wsk);     //adres wskaznika
printf("%p",wsk);     //adres na ktory wskazuje wskaznik
printf("%d",*wsk);    //wartosc(jakas) pod adresem wsk

jesli dobrze wiem funkcja skopiuje ten adres i porusza sie na kopii ale kopia nadal wskazuje na dany adres zatem ja moge zmieniac wartosc pod danym adresem(czyli na oryginale) i teraz moje pytanie skoro ja przekazuje adres wskaznika &wsk  czyli adres wskaznika do dlaczego przypisuje wskaznik do *wsk w postaci
 

*wsk = malloc(N * sizeof(int));

to na co bedzie wskazywalo samo wsk?
To troche tak jakbym przypisywal wskaznik do wartosci ktora jest przechowywana pod adresem na ktory wskazuje wskaznik<?>

2.Funkcja malloc zwraca wskaznik na przyznana pamiec  albo NULL jak sie nie uda przeprowadzic poprawnie procesu , dlaczego zatem spotkac mozna zapis
 

*wsk = (int*)malloc(N * sizeof(int))

ktory rzutuje zwrocony wskaznik na konkretny typ?Gdzies spotkalem informacje ze gdy nie dolacze biblioteki 

#include <stdlib.h>

to wtedy zwracany wskaznik jest bez typu ?Wiec po co i w jakich przypadkach jedna i druga forma

komentarz 11 czerwca 2020 przez j23 Mędrzec (195,220 p.)

to na co bedzie wskazywalo samo wsk?

Będzie wskazywać na zmienną wskaźnikową zdefiniowaną w main, której adres został przekazany w parametrze.

dlaczego zatem spotkac mozna zapis [...] ktory rzutuje zwrocony wskaznik na konkretny typ?

Pewnie dlatego, że ten, kto pisał ten kod, kompilował go kompilatorem C++. W czystym C rzutowanie void*typ* nie jest potrzebne.  C++ pod tym względem jest bardziej restrykcyjny.

Podobne pytania

0 głosów
1 odpowiedź 89 wizyt
pytanie zadane 18 czerwca 2017 w C i C++ przez pimpek Użytkownik (680 p.)
0 głosów
2 odpowiedzi 174 wizyt
0 głosów
1 odpowiedź 142 wizyt

92,834 zapytań

141,778 odpowiedzi

320,826 komentarzy

62,164 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

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!

...