SUSE bonus leaderboard
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)

GFI

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ě.

Odpovědět

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

7 důvodů, proč provozovat řešení SAP na SUSE

SusePři provozování systému SAP HANA nebo S/4HANA potřebujete výkonnou a stabilní platformu, které důvěřuje sama společnost SAP. Společnost SUSE poskytuje špičkovou platformu, která je v souladu se strategií společnosti SAP pro Digital Core.

Pokračování ...


SUSE

Redakční blog

Pavel Fric

Pavel Fric, 21. August

Sayonara Player 1.5.1

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


Pavel Fric

Pavel Fric, 26. January

MuseScore 3

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


Redakce

Redakce, 21. December

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 »