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

C++ wskaźniki

Object Storage Arubacloud
0 głosów
417 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 (194,920 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,000 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

+1 głos
1 odpowiedź 263 wizyt
pytanie zadane 7 maja 2023 w C i C++ przez kwkstein Nowicjusz (150 p.)
0 głosów
1 odpowiedź 367 wizyt
pytanie zadane 30 listopada 2022 w C i C++ przez Pysa6 Nowicjusz (220 p.)
0 głosów
1 odpowiedź 121 wizyt
pytanie zadane 28 lipca 2020 w C i C++ przez Feszyn F Flora Początkujący (320 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

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

...