Smerníky

Pamäť

Pamäť počítača je ako pole v ktorom su za sebou uložené bajty, ako elementárne pamäťové miesta. Každé z nich ma svoju jednoznačnú adresu.

Smerník

Smerník je premmenná, ktorá si pamätá adresu v pamäti.

Deklarácia:

Pascal:
  var pi:^integer;
  var pi,pj:^integer;

C:
  int *pi;
  int *pi, *pj, pk;   // pozor pk, nieje smerník ale premenná typu int
  
  //pomocou definicie typu smerník
  typedef *p_int;
  p_int pi, pj, pk; // pi, pj, pk sú smerníky

Operátory:

* - dereferenčný
& - referenčný
Pomocou operátora * môžeme získať hodnotu z adresy, na ktorú nám ukazuje smerník (napr. i=*pi).
Pomocou operátora & môžeme zasa získať adresu premennej, v ktorej je uložená nejaká hodnota (napr. pi=&i).

Pozor! Všimnime si!

  int i, *pi = &i;
čo je definícia pi a jeho súčasná inicializácia adresou premmennej i
  int i, *pi;
  pi=&i;
čo je priraďovací príkaz, ktorý priradí adresu premennej i do smerníka pi

Pozor na príkazy!

 
  *(pi + 1) = 5    // prepisujeme pamäťové miesto nasledujúce za miestom kde ukazuje smerník 
V tomto prípade sa do smerníka uloží pamäťové miesto nasledujúce za pamäťovým miestom uloženým v smerníku, a na toto miesto sa zapise hodnota 5. Hrozí nebezpečenstvo prepísania nejakých doležitých dát v pamäti.
 
  int *pi;
  *pi = 1; //prepisujeme náhodné miesto v pamäti 
Skúsme si !
  int i[2], *pi, j, k;

  i[0] = 1;
  i[1] = 2;

  pi = &i[0]; // ulozi do pi adresu prveho prvku pola

  j = *pi++;
  k = *pi;
Otázky:
Aké hodnoty budú obsahovať premmenné j, k na konci tohoto programu ?

Hinty:
* má vyššiu prioritu ako +
* má rovnakú prioritu ako ++

Použitie Sizeof :
 Sizeof + premenná  - veľkosť premennej v Bajtoch
 Sizeof + (typ)     - zistí, koľko Bajtov by zaberala v pamäti premenná uvedeného typu

Netypové vs typové smerníky:

  void *adr;
  int *pi, i;
  
  adr = &i;
  pi  = adr;   // <- tu nám kompilátor zahlási chybu
Totiž nemôžeme priradiť hodnotu netypového smerníka typovému. Netypový smerník musíme najprv pretypovať.
  pi  = (int*)adr;

Smerník ako parameter funkcie!

Ako používame smerník ako parameter funkcie a ako potom takú funkciu voláme si ukážeme na príklade. Spravme si funkciu na increment premennej typu integer podobnu ako je v pascale funkcia inc.
  void inc( int *p){
    *p++;
  };
  //-----volanie v programe-----//
  int i=5;
  inc(&i);
  // i == 5
Ako sme si určite všimli, toto nám fungovať nebude. Ako sme už spomínali, operátor * ma rovnakú prioritu ako operátor ++ a teda sa len smerník, ktorý ukazoval na i posunie na dalšiu adresu. Premenná i sa teda nemení.
Spravme si teraz takú, ktorá bude fungovať.
  void inc( int *p){
    (*p)++;
  };
  //-----volanie v programe -----//
  int i=5;
  inc(&i);
  // i == 6
V tomto prípade sme určili precedenciu operátorov.

DÚ:

Spravte funkciu void vymen( int *px, int *py), ktorá vymení hodnoty premmenných pomocou smerníkov.