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

Problem ze wskaznikami

Mały hosting, OGROMNE możliwości
0 głosów
506 wizyt
pytanie zadane 15 listopada 2015 w C i C++ przez Baakoma Użytkownik (780 p.)

Witam, chciałem spróbować napisać program, który najpierw utworzy dynamiczną tablicę, potem ją usunie, utworzy nową, a w funkcji dodaj() przekaze nową tablicę i ją zwiększy o 1. Niestety mam problem, program wywala losowo w różnych miejscach i nie działa tak jak powinien ;/ Od wczoraj w nocy bawię się i nie potrafię znaleźć problemu ;/ Prosiłbym o wytłumaczenie co robię nie tak, z góry dziękuję.Tutaj kod:

#include <iostream>


using namespace std;

void dodaj(int *t, int w, int l);

int main()
{
    int * tab = new int[10];
    for (int i = 0; i < 10; i++)
    {
        *tab = i;
        cout << "Adres pierwszej tablicy: " << (int)tab << endl;
        cout << "Wartosc pierwszej tablicy: " << *tab << endl;
        tab++;
    }
    cout << endl << "Tworzenie drugiej tablicy" << endl << endl;
    delete [] tab;

    tab = new int[11];
    for (int i = 0; i < 11; i++)
    {
        *tab = i*i;
        cout << "Adres drugiej tablicy: " << (int)tab << endl;
        cout << "Wartosc drugiej tablicy: " << *tab << endl;
        tab++;
    }
    cout << endl << "Powiekszanie tablicy" << endl << endl;
    dodaj(tab,11,666);

    delete [] tab;
    return 0;
}

void dodaj(int *tab, int wielkosc, int liczba)
{
    int * newTab = new int[wielkosc+1];
    for (int i = 0; i < wielkosc; i++)
    {
        newTab[i] = tab[i];
        cout << "Adres talibcy dla newTab: " << (int) newTab++ << endl << endl;
        cout << "Wartosc talibcy dla newTab: " << *newTab << endl;
        cout << endl;
        cout << "Adres tablicy dla tab: " << (int)tab << endl << endl;
        cout << "Wartosc talibcy dla Tab: " << *tab << endl;
        tab++;
    }
    newTab[wielkosc] = liczba;
    if(tab) delete [] tab;
    cout << "Obecny adres newTab: " << (int)newTab << endl;
    tab = newTab;
    cout << endl;
    cout << "Adres tablicy dla tab po zmianie: " << (int)tab++ << endl << endl;
    cout << "Wartosc talibcy dla Tab po zmianie: " << *tab << endl;
}

 

1 odpowiedź

0 głosów
odpowiedź 15 listopada 2015 przez Krawiec91 Pasjonat (19,600 p.)

Przyczyną problemów jest wskaźnik tab, a mianowicie:
1. W pierwszej petli for, w każdym przejściu pętli inkrementujesz ten wskaźnik. Następnie próbujesz zwolnić pamięć. Problem w tym, że zwalniasz nie tą pamięć, której żądałeś za pomocą operatora new. Wskaźnik tab przed pętlą, ma inną wartość, niż po wykonaniu pętli.
2. W drugie pętli for podobna sytuacja związana z inkrementacją wskaźnika. Z tą różnicą, że po wykonaniu pętli do funkcji dodaj() nie przekazujesz tablicy, którą zaalokowałeś wcześniej, tylko zawartość pamięci znajdującą się bezpośrednio za tablicą.

A żeby tego uniknąć, to możesz sobie zadeklarować pomocniczy wskaźnik na typ, do którego przypiszesz adres tablicy i będzie mógł z użyciem tego wskaźnika przesuwać się po kolejnych polach tablicy. Zawsze też będziesz mógł się odwołać do oryginalnego wskaźnika (nazwa tablicy). Inną opcją jest, użycie notacji ze wskaźnikiem:
 

for (int i=0;i<10;i++)
{
  *(tab+i)=i;
  cout<<"Adres pierwszej tablicy: "<<(int)(tab+i)<<endl;
  cout<<"Wartosc pierwszej tablicy: "<<*(tab+i)<<endl;
}

Adres jaki przechowuje wskaźnik jest nieruszony, dostęp do kolejnych elementów jest możliwy dzięki zwiększaniu przesuniecia (zmienna i) względem początku tablicy. Na jedno wychodzi, tylko z tą różnicą, że nie zmienia się wartość wskaźnika.

komentarz 15 listopada 2015 przez Baakoma Użytkownik (780 p.)
edycja 15 listopada 2015 przez Baakoma

Niestety dalej nie wiem, czy jest dobrze, adresy się nie zgadzają, chyba się w tym wszystkim pogubiłem ;/

Czy jeśli robie przypisanie tab = newTab; to tab nie powinien mieć ten sam adres co newTab ? Dlaczego 1 i 2 tablica ma te same adresy, choć usuwam poprzednią tablicę ?

#include <iostream>

using namespace std;

void dodaj(int *t, int w, int l);

int main()
{
    int * tab = new int[10];
    for (int i = 0; i < 10; i++)
    {
        *(tab+i) = i;
        cout << "Adres pierwszej tablicy: " << (int)(tab+i)<< endl;
        cout << "Wartosc pierwszej tablicy: " << *(tab+i) << endl;
    }
    cout << endl << "Tworzenie drugiej tablicy" << endl << endl;
    delete [] tab;

    tab = new int[11];
    for (int i = 0; i < 11; i++)
    {
        *(tab+i) = i*i;
        cout << "Adres drugiej tablicy: " << (int)(tab+i) << endl;
        cout << "Wartosc drugiej tablicy: " << *(tab+i) << endl;
    }
    cout << endl << "Powiekszanie tablicy" << endl << endl;
    dodaj(tab,11,666);

    cout << endl << endl << endl;

    for (int i = 0; i < 12; i++)
    {
        cout << "Adres tablicy dla tab po zmianie: " << (int)(tab+i) << endl;
        cout << "Wartosc talibcy dla Tab po zmianie: " << *(tab+i) << endl << endl;
    }
    delete [] tab;
    return 0;
}

void dodaj(int *tab, int wielkosc, int liczba)
{
    int * newTab = new int[wielkosc+1];
    cout << "Poczatkowy newTab: " << (int)newTab << endl;
    for (int i = 0; i < wielkosc; i++)
    {
        newTab[i] = tab[i];
        cout << "Adres talibcy dla newTab: " << (int)(tab+i) << endl << endl;
        cout << "Wartosc talibcy dla newTab: " << *(newTab+i) << endl;
        cout << endl;
        cout << "Adres tablicy dla tab: " << (int)(tab+i) << endl << endl;
        cout << "Wartosc talibcy dla Tab: " << *(tab+i)<< endl;
    }
    newTab[wielkosc] = liczba;
    if(tab) delete [] tab;
    cout << "Obecny adres newTab: " << (int)newTab << endl;
    tab = newTab;
    newTab = NULL;
}

 

Podobne pytania

0 głosów
1 odpowiedź 225 wizyt
0 głosów
1 odpowiedź 443 wizyt
0 głosów
1 odpowiedź 345 wizyt

93,717 zapytań

142,629 odpowiedzi

323,261 komentarzy

63,261 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

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...