Mutató (adattípus)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2021. április 11-én felülvizsgált verziótól ; az ellenőrzések 11 szerkesztést igényelnek .

A pointer ( angol  pointer ) egy olyan változó , amelynek értéktartománya memóriacellák címeiből vagy egy speciális érték- nulla címből áll . Ez utóbbi arra szolgál, hogy jelezze, hogy a mutató jelenleg nem hivatkozik egyik érvényes cellára sem. A mutatókat Jekaterina Logvinovna Juscsenko találta fel a címprogramozási nyelvben (1955), és nem Harold Lawson 1964-ben, ahogyan azt külföldön sokáig hitték [1] . 1955- ben az Address Programming Language bevezette a közvetett címzés és a magasabb rangú címzés fogalmát, amely lefedi a mutató fogalmát és hatókörét a modern programozási nyelvekben.

Hatókör

A mutatókat két területen használják:

Műveletek a mutatókon

A mutatók típusát biztosító programozási nyelvek általában két alapvető műveletet tartalmaznak: hozzárendelést és hivatkozást .

1955-ben az Address Programming Language (USSR) bevezette a „bar-operációt” (pointer dereferencing), amelyet hardverben a kijevi számítógép processzorának F-működésével valósított meg (1955) , majd később az M-20- ban. számítógépek , „ Dnepr ”, a BESM család számítógépei (BESM-2, BESM-3, BESM-3M és BESM-4), a minszki és urali családok, valamint néhány más szovjet gyártású számítógép. A mutatóhivatkozás többszörös használatát ezeken a számítógépeken a hardverben is megvalósították csoportcím-frissítési műveletekkel, hogy felgyorsítsák a faszerű formátumokkal végzett munkát (a listák és más absztrakt adattípusok a faszerű formátumok speciális esetei).

Az első valamilyen címet rendel a mutatóhoz. A második a mutató által mutatott memória érték elérésére szolgál. A hivatkozás megszüntetése lehet explicit vagy implicit; a legtöbb modern programozási nyelvben a hivatkozás megszüntetése csak akkor történik meg, ha kifejezetten meg van határozva[ mi? ] .

Példa a mutatókkal való munkára a C nyelvben :

int n = 6 ; // Egy int típusú n változó deklarálása és 6 érték hozzárendelése int * pn = malloc ( sizeof ( int ) ); // A pn ​​mutató deklarálása és memóriafoglalás hozzá * pn = 5 ; // A mutató visszaállítása és az 5. érték hozzárendelése n = * pn ; // n hozzárendelése a pn free ( pn ) által mutatott értékhez (5 ); // Az elfoglalt memória felszabadítása pn = & n ; // Pn mutató hozzárendelése az n változó címéhez (a mutató n-re fog mutatni) n = 7 ; // *pn is egyenlő lett 7-tel

Az unáris operátor &a változó címét adja vissza, és az operátor a hivatkozás megszüntetésére *szolgál:

int forrásNum1 = 100 ; int forrásSzám2 = 200 ; int * pNum1 = & sourceNum1 ; int * pNum2 = & sourceNum2 ; printf ( "1-%d, 2-%d mutató értéke \n " , * pNum1 , * pNum2 ); pNum1 = pNum2 ; printf ( "1-%d, 2-%d mutató értéke \n " , * pNum1 , * pNum2 );

Ha a mutató egy objektum címét tárolja, akkor azt mondják, hogy a mutató erre az objektumra hivatkozik vagy rámutat .

Azoknak a nyelveknek, amelyek biztosítják a mutatók használatát a dinamikus memóriafoglaláshoz , tartalmazniuk kell egy operátort a változók memóriabeli explicit lefoglalására. Egyes nyelvekben ezen az operátoron kívül létezik egy operátor is a változók memóriából való explicit törlésére. Mindkét művelet gyakran beépített rutinok formájában történik (a malloc és free függvények C-ben, a new és delete operátorok a C++-ban stb.). Ha egyszerű mutatót használ, nem pedig intelligens mutatót , a memóriaszivárgások elkerülése érdekében mindig törölje a változót a memóriából .

Mutató érvénytelenítéséhez

A void típusú mutató lehetővé teszi, hogy bármilyen adattípusra hivatkozzon , beleértve egy osztályt is . Ez a technológia a Boost könyvtár bármely típusának az alapja .

osztály { _ int mező ; }; AclA ; _ void * pA = ( érvénytelen * ) & clA ; // A pA mutató egy A osztályú objektumra hivatkozik

Mutató a mutatóra (magasabb rangok megszólítása)

A programozásban is vannak mutatók a mutatókra. Memóriacímeket tárolnak, ahol mutatók vannak arra a memóriára, ahol az adatobjektum található, vagy egy másik mutatót. Ha egy mutatót egy mutatóhoz láncolunk, amely ismét egy mutatóra mutat, lehetővé teszi számunkra, hogy bemutassuk a többszörös mutató dereferálás fogalmát (a címprogramozási nyelvben : "magasabb rangok megszólítása" ) , valamint a mutatókra vonatkozó megfelelő műveletet: többszörös indirection.

int x , * p , ** q ; x = 10 ; p = & x ; q = & p ; // pointer to pointer printf ( "%d" , ** q );

Null mutató

A nullmutató egy olyan mutató, amely egy speciális értéket tartalmaz, jelezve, hogy az adott mutatóváltozó nem hivatkozik (nem mutat rá) egyetlen objektumra sem. A programozási nyelvekben ezt egy speciális konstans jelöli [4] :

Fő alkalmazási problémák

A mutatókat nehéz kezelni. Elég könnyű rossz értéket írni egy mutatóba, ami nehezen reprodukálható hibát okozhat. Például véletlenül megváltoztatta egy mutató címét a memóriában, vagy helytelenül foglalta le a memóriát az információk számára, és itt meglepetés várhat rád: egy másik nagyon fontos változó, amelyet csak a programon belül használunk, felülíródik. A hiba pontos helyét megérteni és reprodukálni nem lesz egyszerű, az ilyen hibák kiküszöbölése pedig nem mindig triviális feladat, néha a program jelentős részét át kell írni [6] .

Néhány probléma megoldására vannak védelmi és biztosítási módszerek:

Mutatók inicializálása

Példa egy inicializálatlan mutató hibájára:

/* a program érvénytelen. */ int main ( érvénytelen ) { int x , * p ; // Lefoglalt memória x-hez, de nem *p x = 10 -hez ; // A memória írása 10 * p = x ; // A 10 egy meghatározatlan helyre íródik a memóriában, ami a program összeomlását okozhatja. return 0 ; }

Egy ilyen kis programnál a probléma észrevétlen maradhat. De amikor a program növekszik, hirtelen világossá válhat, hogy a változó más, a program számára fontos adatblokkok közé van írva. Ennek elkerülése érdekében inicializálja a [6] mutatót .

A mutatók helyes használata

A mutató helytelen használata:

#include <stdio.h> /* a program érvénytelen */ int main ( érvénytelen ) { int x , * p ; x = 10 ; p = x ; printf ( "%d" , * p ); return 0 ; }

A hívás printf()nem jeleníti хmeg a képernyőn a 10 értékét. Ehelyett valamilyen ismeretlen érték kerül kiadásra – ez a hozzárendelési operátor ( р = х;) helytelen használatának az eredménye. Ez az operátor a 10-es értéket rendeli a mutatóhoz р, amelynek a címet kell tartalmaznia, nem az értéket. Szerencsére ebben a programban a hibát észleli a fordító – figyelmeztetést ad a szokatlan mutatókonverzióról. A hiba kijavításához írja be p = &х;[6] .

A mutató helyes használata
  • próbálja meg azonnal inicializálni a változókat, amikor deklarál ( int x = 10;);
  • ne keverje össze a mutatókat normál változókkal (például int x, *p, y, *y_ptr;);
#include <stdio.h> int main ( érvénytelen ) { int x = 10 ; int * p = & x ; printf ( "%d" , * p ); return 0 ; }

Memóriaszivárgás

A memóriaszivárgás  a számítógép szabad véletlen hozzáférésű memóriájának (RAM) mennyiségének ellenőrizetlen csökkenésének folyamata, amely a futó programok hibáihoz kapcsolódik, amelyek nem szabadítják fel időben a felesleges memóriaterületeket, vagy a rendszermemória-vezérlő szolgáltatások hibáival.

char * mutató = NULL ; int i = 0 ; for ( i = 0 ; i < 10 ; i ++ ) { pointer = ( char * ) malloc ( 100 ); // A memória 10-szer foglal le } szabad ( mutató ); // A csak az utolsó esetben szabadul fel

Mutatók összehasonlítása

A mutatókhoz rendelt memóriacímek összehasonlíthatók. pNum1 < pNum2A és az űrlap összehasonlítása pNum1 > pNum2gyakran egy tömb elemeinek szekvenciális iterálására szolgál egy ciklusban : pNum1megfelel a memória aktuális pozíciójának és pNum2 a tömb végének. pNum1 == pNum2igazat ad vissza, ha mindkét mutató ugyanarra a memóriahelyre mutat.

Cím aritmetika

A címaritmetika az assembly nyelvekből örökölt pointerek gondolatának logikus folytatásaként jelent meg: az utóbbiban lehetőség van némi eltolás jelzésére az aktuális pozíciótól.

A címaritmetika tipikus műveletei:

int * p ; // Tegyük fel, hogy p a 200 címre mutat p ++ ; // Növekedés után 200-ra mutat + sizeof(int) = 204 p -- ; // Most 200-ra mutat vissza.

Intelligens mutató

Egyes programozási nyelvekben vannak olyan osztályok (általában sablonok), amelyek a mutató interfészt olyan új funkciókkal valósítják meg, amelyek kijavítják a fent említett hiányosságok egy részét.

Egy index az emberi biológiában

Az agy mutatószerű sejtcsoportokat használ az új információk emlékezésével kapcsolatos egyes feladatok elvégzésére [7] .

Jegyzetek

  1. Videla, Alvaro Kateryna L. Juscsenko - A mutatók feltalálója  . https://medium.com/ . A számítástechnika korszakának saját úttörőinek számítógépe (2018. december 8.). Letöltve: 2020. július 30. Az eredetiből archiválva : 2020. szeptember 23.
  2. Mire használják a mutatókat? . Letöltve: 2013. február 20. Az eredetiből archiválva : 2013. február 26..
  3. 14.1. Memóriakiosztás (downlink) . - „A lefoglalt memória kezdetének címe visszakerül a függvényhívás pontjára, és a mutatóváltozóba íródik. Az így létrehozott változót dinamikus változónak nevezzük. Letöltve: 2013. február 22. Az eredetiből archiválva : 2013. június 25. 
  4. 5.1. kérdés . comp.lang.c Gyakran Ismételt Kérdések. Letöltve: 2013. február 20. Az eredetiből archiválva : 2013. február 26..
  5. A nullmutató neve:  nullptr . JTC1.22.32 . JTC1/SC22/WG21 – A C++ Szabványügyi Bizottság (2007. október 2.). Hozzáférés dátuma: 2010. október 4. Az eredetiből archiválva : 2012. február 11.
  6. 1 2 3 Mutatókkal kapcsolatos problémák . Letöltve: 2013. február 22. Az eredetiből archiválva : 2013. február 26..
  7. Az agy programozási trükköket használ új problémák megoldására . RIA Novosti (2013. szeptember 23.). Letöltve: 2016. szeptember 13. Az eredetiből archiválva : 2016. szeptember 20.