přejít na obsah přejít na navigaci

Linux E X P R E S, Programovanie v jazyku C++: Pointery – Tipy a triky (4)

CADservis

Programovanie v jazyku C++: Pointery – Tipy a triky (4)

cplusplus.png

Máme niekoľko možností kombinácie pointerovej aritmetiky a dereferenčného operátora. Okrem ukážok si o každej možností niečo povieme, napr. ako sa vyvarovať potencionálnych chýb s pamäťou.


Tipy a triky pri pointerovej aritmetike

Ukážme si príklady, kedy pointerová aritmetika môže zmiasť a programátor nedopatrením urobí chybu, ktorá sa mu môže vypomstiť. Uvidíme tri rôzne možností, ako môžete využiť nakombinovať pointerovú aritmetiku.

V prvom príklade využijeme tento tvár: *ptr++.

#include <iostream>
using namespace std;
 
int main()
{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole;
 
    for(int i = 0; i < 3; i++)
    {
        cout << *ptr++ << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0;
}

Výstup programu:

55 22 78
Ukazovatel ukazuje: 91

Použitím *ptr++ dôjde najprv k inkrementácii adresy a potom a teraz pozor, dereferencia sa týka predošlej adresy, nie aktuálnej po inkrementácii!. Prečo to funguje takto podivné? Pretože postfix ++ má prednosť pred prefixom, ktorý predstavuje znak dereferencie *. Avšak pri tomto definovaní sa tiež môžete ľahko dostať do problému s pamäťou. Ak by ste chceli vypísať celé pole, tak pri poslednej iterácii dôjde k tomu, že pointer bude ukazovať mimo vašu vyhradenú pamäť a môže dôjsť v tom lepšom prípade len k pádu programu. Ako sa brániť proti tomuto druhu potencionálnej chyby? Napr. pridaním podmienky if/else.



#include <iostream>
using namespace std; 
int main()
{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole; 

    for(int i = 0; i < 7; i++)
    {
        if(i != 6)
            cout << *ptr++ << " ";
        else cout << *ptr << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0; }

Výstup programu:

55 22 78 91 27 187 155
Ukazovatel ukazuje: 155

Druha možnosť využitia pointerovej aritmetiky je v tváre  *++p.

#include <iostream>
using namespace std; 

int main()
{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole; 

    for(int i = 0; i < 3; i++)
    {
        cout << *++ptr << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0;
}

Výstup programu:

22 78 91 Ukazovatel ukazuje: 91

Ak sú oba operátory prefixové, čiže majú rovnakú prioritu a vtedy sa vykonávajú operátory sprava do ľavá. Najprv sa inkrementuje adresa pointera a následne sa aplikuje dereferenčný operátor.

Problémy s pamäťou sa iste objavia, ak si neustriehnete pridelený blok pamäte. Skúsme sa pozrieť na alternatívne riešenie odlišné od prvého riešenia tak, aby sme skúsili viacero možností v tomto dieli.

#include <iostream>
using namespace std; 
int main()

{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole; 
    for(int i = 0; i < 7-1; i++)
    {
        cout << *++ptr << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0;
}

Výsledok programu:

22 78 91 27 187 155 Ukazovatel ukazuje: 155

Vyriešili sme to tak, že sme počet iterácii obmedzili podmienkou i < 7-1, kde 7 je počet prvkov v polí a od toho odčítame práve tu poslednú problematickú iteráciu. Ako z pointera zistiť veľkosť poľa sa dozviete v jednom z ďalších dieloch. Zatiaľ sme to definovali takto provizórne.

A teraz sa pozrime na poslednú tretiu možnosť pointerovej aritmetiky.

#include <iostream>
using namespace std; 
int main()
{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole; 
    for(int i = 0; i < 3; i++)
    {
        cout << ++*ptr << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0;
}

Výsledok programu:

56 57 58 Ukazovatel ukazuje: 58 

Pri tretej možností kombinácie pointerovej aritmetiky s dereferenčným operátorom ++*ptr, opäť nastáva to, že oba operátory sú prefixy, čiže majú rovnakú prioritu. Vykonaním sprava do ľavá najprv sa aplikuje dereferenčný operátor a následne sa inkrementuje hodnota prvku, ktorú sme získali dereferenčným operátorom a nie adresa! Nikdy nedôjde k zmene adresy! Taktiež nehrozí žiadny problém s pamäťou, pretože stále bude pointer ukazovať na ten istý prvok. Presvedčme sa.

#include <iostream>
using namespace std; 
int main()
{
    int pole[] = {55,22,78,91,27,187,155};
    int *ptr = pole; 
    for(int i = 0; i < 25; i++)
    {
        cout << ++*ptr << " ";
    }
    cout << "\nUkazovatel ukazuje: " << *ptr;
    return 0;
}

Výsledok programu:

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
Ukazovatel ukazuje: 80 

Námet na tento článok poslúžili tieto zdroje:

Difference between ++*p, *p++ and *++p, geeksforgeeks.org, dostupné online

Can you explain the difference between *ptr++ and *(++ptr)? [duplicate], stackoverflow.com, dostupné online






Nahoru

Příspěvky

Programovanie v jazyku C++: Pointery – Tipy a triky (4)
T0m 6. 02. 2019, 00:16:10
Odpovědět  Odkaz 
No snad bude i neco o smart pointerech nekdy příště.

Přidat názor

Nejsou podporovány žádné značky, komentáře jsou jen čistě textové. Více o diskuzích a pravidlech najdete v nápovědě.
Diskuzi můžete sledovat pomocí RSS kanálu rss



 
 

Top články z OpenOffice.cz

Eduard Boldižár

Eduard Boldižár

Som redaktorom stránky astrotech.cz. Mám 25 rokov. Medzi moje záľuby patrí astronómia, sci-fi literatúra a programovanie.


  • Distribuce: ubuntu
  • Grafické prostředí: unity



Public Relations

Při testování nových vozů pomáhá Samsung Knox: příručka, navigace i určování polohy v jednom

Samsung KnoxBezpečnostní platforma Samsung Knox sehrála výraznou roli při představování Škody Karoq. Knox Configure a Knox Manage pomohly připravit stovky vozů pro dovozce a obchodníky.

Pokračování ...


Infor

Public Relations

S obrovským nárůstem dat by mohla pomoci umělá inteligence

LenovoO chytrých technologiích, IoT zařízeních a umělé inteligenci (AI) slýcháme poměrně často v nejrůznějších souvislostech. Pomalu ale jistě pronikají nejen do našich soukromých životů, ale také do fungování ve firmách. Málo se už ale mluví o jejich počtech a také o množství dat, která tato zařízení produkují. Obě hodnoty přitom neustále rostou.

Pokračování ...


Redakční blog

Pavel Fric

Pavel Fric, 21. srpen

Sayonara Player 1.5.1

Přehrávač, jak má být. Poslední dobou vývoj šlape


Pavel Fric

Pavel Fric, 26. leden

MuseScore 3

První aktualizace třetí řady notačního editoru MuseScore


Redakce

Redakce, 21. prosinec

Pište pro LinuxEXPRES

Baví vás Linux? Pište o něm, není to nic těžkého. LinuxEXPRES hledá nové autory.


Všechny blogy »

Alvao