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

C++ wskaźniki

42 Warsaw Coding Academy
0 głosów
770 wizyt
pytanie zadane 3 października 2021 w C i C++ przez kevinbarakuda888 Nowicjusz (120 p.)

Witam

jestem narazie początkujący w programie oglądam właśnie

Kurs C++ odc. 10: Wskaźniki. Dynamiczne alokowanie pamięci

na Youtube robie wszystko jak na filmie linijka po linijce ale wyskakuje mi błąd mianowicie chodzi mi o

#include <iostream>
#include <time.h>
#include <cstdlib>

using namespace std;

int ile;

clock_t start, stop;
double czas;

int main()
{
    cout << "Ile liczb w tablicy: ";
    cin>>ile;

    int *tablica;
    tablica = new int [ile];
    start=clock();
    for (int i=0; i<ile; i++)
    {
        tablica[i]=i;
        tablica[i]+=50;
    }
    stop=clock();
    czas=(double)(stop-start)/CLOCKS_PER_SEC;
    cout<<"czas zapisu (bez wskaznika): "<<czas<<endl;

    delete []tablica;

    int *wskaznik=tablica;
    tablica=new int [ile];

    start=clock();
    for (int i=0; i<ile; i++)
    {
        *wskaznik=i;
        *wskaznik+=50;
        wskaznik++;
    }
    stop=clock();
    czas=(double)(stop-start)/CLOCKS_PER_SEC;
    cout<<"czas zapisu (z wskaznikiem): "<<czas<<endl;

    delete []tablica;

    return 0;
}

 

i tu pojawia się problem bo przy ostatnim cout nie pokazuje mi się konsoli z wskaźnikiem tylko ta pierwsza opcja co ciekawe kiedy daje mniejsze liczby jest wporządku obydwie opcje się pokazują

a przy większej jest to

może w opcjach coś jeszcze powpisywać, wiem z poprzednich że przy większych liczbach co int sobie nie radzi jest long double tylko teraz w które miejsca to wstawić wszędzie tam gdzie jest int czy tylko w niektórych

Proszę o pomoc

1 odpowiedź

+3 głosów
odpowiedź 4 października 2021 przez Whiskey_Taster Pasjonat (15,610 p.)
edycja 4 października 2021 przez Whiskey_Taster

Problem leży w linii nr 31 i tym, co zostało zrobione w linii nr 29. Gdy wykonujemy operację przypisania na wskaźnikach, to tak naprawdę do wskaźnika po prawej stronie operatora zostaje przypisany adres, na który wskazuje wskaźnik po prawej stronie. I nie ma w tym nic złego, jeśli tuż przed przypisaniem alokujesz pamięć na nowo. Tyle tylko, że tego nie zrobiłeś, bo po zwolnieniu pamięci robisz od razu przypisanie i dopiero potem alokujesz pamięć na nowo. Więc do wskaźnika 'wskaznik' masz przypisany adres pamięci, która została już zwolniona, a do wskaźnika 'tablica' masz przypisany nowy adres pamięci. 

Poniżej zamieszczam kod, który pokazuje, jak to mniej więcej działa: 
 

int main()
{
	int* p1 = new int{ 5 };
	int* p2 = new int{ 6 };

	std::cout << "*p1: " << *p1 << '\n';
	std::cout << "&p1: " << &p1 << '\n';
	std::cout << "&*p1: " << &*p1 << '\n';

	std::cout << '\n';

	std::cout << "*p2: " << *p2 << '\n';
	std::cout << "&p2: " << &p2 << '\n';
	std::cout << "&*p2: " << &*p2 << '\n';

	std::cout << '\n';

	p1 = p2;
	std::cout << "After assignment: " << '\n';
	std::cout << "*p1: " << *p1 << '\n';
	std::cout << "&p1: " << &p1 << '\n';
	std::cout << "&*p1: " << &*p1 << '\n';

	std::cout << "*p2: " << *p2 << '\n';
	std::cout << "&p2: " << &p2 << '\n';
	std::cout << "&*p2: " << &*p2 << '\n';

	std::cout << '\n';

	delete p2;

	p2 = new int{ 3 };
	std::cout << "After new on p2 : " << '\n';

	std::cout << "*p1: " << *p1 << '\n';
	std::cout << "&p1: " << &p1 << '\n';
	std::cout << "&*p1: " << &*p1 << '\n';

	std::cout << "*p2: " << *p2 << '\n';
	std::cout << "&p2: " << &p2 << '\n';
	std::cout << "&*p2: " << &*p2 << '\n';

	return 0;
}

Ten twór typu '&*p1' oznacza pokazanie adresu wyłuskanej wartości ze wskaźnika p1. Innymi słowy adres, na który wskazuje wskaźnik :)

A jeśli chodzi o rozwiązanie problemu: wystarczy przesunąć alokację pamięci przed przypisanie, to jest zamienić linie nr 31 i 32 miejscami.

 

PS: Generalnie fakt, że raz Ci zadziałało, a za innym razem nie, wynika z tego, że kompilator, którego używasz pozwala na coś takiego i nie krzyczy, że coś tu jest nie w porządku. 

komentarz 4 października 2021 przez j23 Mędrzec (195,240 p.)

Kompilatory raczej nie wyłapują tego typu błędów.

A jeśli chodzi o rozwiązanie problemu: wystarczy przesunąć alokację pamięci przed przypisanie, to jest zamienić linie nr 31 i 32 miejscami.

IMO powinien usunąć linie 29 i 32.

komentarz 4 października 2021 przez Whiskey_Taster Pasjonat (15,610 p.)

Fakt, to już w czasie działania programu błąd. Co w takim razie wyłapuje takie błędy w trybie debugowania programu? U mnie VS krzyczy, że to błąd, jak dochodzi do wykonania instrukcji. 

Tak, można też usunąć linie 29 i 32, założyłem jednak, że autor chce sobie poćwiczyć co nieco.

 

Notka do autora: jak zaczynasz, to polecam stronę learncpp

1
komentarz 4 października 2021 przez tkz Nałogowiec (42,020 p.)
Raczej nie sam kompilator, a jakaś flaga. Sam język zakłada, że wiesz co robisz i po prostu puszcza, przynajmniej tak zakłada standard.
komentarz 4 października 2021 przez kevinbarakuda888 Nowicjusz (120 p.)

@Whiskey_Taster, Dziękuje bardzo za odpowiedź smiley

komentarz 4 października 2021 przez Whiskey_Taster Pasjonat (15,610 p.)

@tkz, okej, dzięki za wyjaśnienie :) 

komentarz 4 października 2021 przez Whiskey_Taster Pasjonat (15,610 p.)

@kevinbarakuda888​​​​​​, nie ma sprawy, cieszę się, że zrozumiałeś :) 

komentarz 8 października 2021 przez Sadako Obywatel (1,240 p.)

@Whiskey_Taster, Tak jak @tkz pisał(a), takie reczy nie są wyłapywane przez kompilator. Takiego typu błędy mogą jednak być wykryte przez dynamiczna i statyczną analizę kodu. Warto się zaznajomić z narzędziami do takiej analizy i stosować na co dzień, bo pomagają uniknąć wielu błędów - zarówno tych klasycznych jak i tych mega skomplikowanych i ciężkich do znalezienia.
Nie jest to panaceum na wszystko i znajdują też false positive, ale zysk jest spory.

 

Podobne pytania

0 głosów
2 odpowiedzi 202 wizyt
pytanie zadane 2 grudnia 2024 w C i C++ przez adam234345 Początkujący (400 p.)
+1 głos
1 odpowiedź 448 wizyt
pytanie zadane 7 maja 2023 w C i C++ przez kwkstein Nowicjusz (150 p.)
0 głosów
1 odpowiedź 609 wizyt
pytanie zadane 30 listopada 2022 w C i C++ przez Pysa6 Nowicjusz (220 p.)

93,379 zapytań

142,380 odpowiedzi

322,533 komentarzy

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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...