english version while1 - stránky o programování

Ukazatel

Popis

Ukazatel umožňuje vytvářet dynamické proměnné, které vznikají a zanikají za běhu programu. Proměnné typu ukazatel obsahují abstrakci adresy umístění dynamické proměnné.

Dynamické proměnné a proměnné typu ukazatel slouží především pro konstrukci dynamických datových typů. Základním dynamickým datovým typem je seznam.

Vývojový diagram

Přirozený jazyk

JSA

Za použitelné datové typy lze považovat dostupné registry procesoru.

Indexregistry

  E 31               15               0
    +----------------+----------------+
ESI |                |       SI       | operace s řetězci (zdrojový) 
EDI |                |       DI       | operace s řetězci (cílový) 
ESP |                |       SP       | operace se zásobníkem
EBP |                |       BP       | bázový registr (adresování paměti)
    +----------------+----------------+

Pascal

ukazatel
Typ ukazatel U je vázán na typ T. Definuje množinu hodnot, které ukazují na element typu T. Proměnná P typu U se nazývá proměnná typu ukazatel vázaná na typ T a identifikuje proměnou typu T. Ukazatel má speciální hodnotu NIL pokud neukazuje na nic (je prázdný = nulový).


ukazatel[ uk.pas ]
program uk;

type          {deklarace typu}
   T = integer; { typ T }
   U = ^T;      { U je typu ukazatel na T }

var           {deklarace promennych}
   P : U;       {promenna typu ukazatel na T}
   H : T;       {promenna typu T}

{zacatek programu ... prikazova cast}
begin
  H := 128;
  P := @H;  { operator @ vrati adresu H }

  {vypis hodnoty ukazatele (128),
   P^ zpristupni odkazovanou hodnotu}
  writeln('P (',P^,'), H (',H,')');

  {pricteni 10 k promenne H pres ukazatel}
  P^ := P^ + 10;

  {hodnota H (138) vypsana pres ukazatel P po pricteni}
  writeln('P (',P^,'), H (',H,')');
end.

dynamická proměnná

Dynamickou proměnnou identifikuje ukazatel vázaný s jejím typem. Samotná dyn. proměnná identifikátor nemá. Pro vytvoření (přidělení paměti) existuje příkaz new() a její zrušení příkaz dispose(). Zrušení (dealokace) proměnné je opravdu nutné, protože jinak zjistíte, že s každým spuštěním programu se vám zmenšuje velikost dostupné operační paměti (RAM).

K zpřístupnění obsahu dynamické proměnné používáme operátor ^. Pro položku strukturovaného typu záznam doplníme ^ před . (výsledek ^.).

Dynamické proměnné mají větší význam při vytváření ADS (Abstraktních Datových Typů) jako jsou: seznam, fronta, zásobník (vše v samostatné kapitole).



dynamická proměnná[ new.pas ]
type          {deklarace typu}
     TKniha = record
         jmeno : string;     {retezec 255 znaku}
         cena  : integer;
         autor : string[10]; {retezec deseti znaku}
     end;

     PKniha = ^TKniha; {typ ukazatel na TKniha}

var           {deklarace promennych}
     kniha : PKniha; {promenna typu PKniha}

{zacatek programu ... prikazova cast}
begin
    kniha := new( PKniha ); {alokace pameti}

    {naplneni zaznamu}
    kniha^.jmeno := 'C++ programovaci jazyk';

    {naplneni zaznamu pres prikaz with}
    with kniha^ do begin
        cena := 699;
        autor := 'Bjarne Stroustrup';
    end;

    writeln('jmeno = ', kniha^.jmeno);
    writeln('cena  = ', kniha^.cena);
    writeln('autor = ', kniha^.autor);

    dispose( kniha );
end.

C/C++

Ukazatel na nějaký typ vytvoříme deklarací s operátorem * hvězda. Pro získání adresy proměnné slouží operátor &. Ukazatel má speciální hodnotu NULL pokud neukazuje na nic (je prázdný = nulový).

ukazatel


ukazatel[ ptr.cpp ]
#include <stdio.h>  // printf()
#include <stddef.h> // NULL
int main (int argc, char *argv[]) {
    typedef int T; //typ T typu cele cislo
    typedef T *U;  //typ U typu ukazatel na T

    U P; // promenna typu ukazatel na T
    T H; // promenna typu T

    H = 128;
    P = &H;  // operator & vrati adresu H

    // vypis hodnoty H pres ukazatel
    printf("P(%d), H(%d) \n", *P, H);    
    
    // pricteni 10 k promenne H pres ukazatel P
    *P = *P + 10;
    
    // vypis hodnoty H pres ukazatel
    printf("P(%d), H(%d) \n", *P, H);  
    return 0;
}

pole jako ukazatel
Proměnná typu pole je zároveň ukazatelem na první prvek.


pole[ array4.cpp ]
#include <stdio.h>
int main (int argc, char *argv[]) {
    int num[3]; // pole celych cisel delky 3
    num[0] = 1;
    num[1] = 7;
    num[2] = 9;
    
    //vytvoreni stejneho pole 'num' jinym zpusobem 
    // int num[] = { 1, 7, 9}; 
    
    int *ptr;   //ukazatel typu int 
    
    ptr = num;  //ptr bude ukazovat na prvni prvek pole
    printf("prvni [%d]\n", *ptr);    
    
    ptr = ptr + 1; //presun ukazatele na druhy prvek
    printf("druhy [%d]\n", *ptr);    
    
    ptr++; //presun ukazatele na treti prvek
    printf("treti [%d]\n", *ptr);        
    
    return 0;
}

dynamická proměnná

Dynamickou proměnnou identifikuje ukazatel vázaný s jejím typem. Samotná dyn. proměnná identifikátor nemá. Pro vytvoření (přidělení paměti) existuje operátor new a její zrušení operátor delete (pro dynamické pole delete[]).

K zpřístupnění obsahu dynamické proměnné používáme operátor -> místo . tečky u statických záznamů.

Dynamické proměnné mají větší význam při vytváření ADS (Abstraktních Datových Typů) jako jsou: seznam, fronta, zásobník (vše v samostatné kapitole).



dynamická proměnná[ new.cpp ]
#include <stdio.h>  // printf()
#include <string.h> // copystr(), copystrn()

#define JMENO_MAX 40  // konstanta preprocesoru
#define AUTOR_MAX 10  // bude dosazena na mista vyskytu

int main (int argc, char *argv[]) {
    // novy datovy typ TKniha
    struct TKniha {
        char jmeno[JMENO_MAX];
        int  cena;
        char autor[AUTOR_MAX];
    }; // strednik !
    
    TKniha *kniha; //promenna typu ukazatel na TKniha
    
    kniha = new TKniha; // prideleni (alokace) pameti
    
    // kopirovani retezce "C++ pr.." do polozky jmeno
    strcpy(kniha->jmeno, "C++ programovaci jazyk");
    kniha->cena = 699;
    
    // kopirovani retezce "Bjarn.." do polozky autor
    // zkopirovano bude maximalne AUTOR_MAX znaku
    strncpy(kniha->autor, "Bjarne Stroustrup", AUTOR_MAX);
    // pro AUTOR_MAX(10) je obsah kniha.autor "Bjarne Str"
    // retezec je nutne ukoncit nulou !        0123456789
    kniha->autor[AUTOR_MAX-1] = '\0';    // autor[9] = 0
    
    // vypis
    printf("jmeno [%s] \n", kniha->jmeno);
    printf("cena  [%d] \n", kniha->cena);
    printf("autor [%s] \n", kniha->autor);
    
    delete kniha; // uvolneni (dealokace) pameti
    
    return 0;
}

dynamické pole
V C (a C++) lze vytvářet dynamická pole proměnné délky. Délka se určí při alokaci paměti a dále zůstává konstantní (neměnitelná). Velikost pole je omezeno pouze dostupnou pamětí (např. lze vytvořit 10 MB pole).


alokovaný řetězec znaků[ array6.cpp ]
#include <stdio.h>  // printf()
#include <string.h> // strlen(), strcpy(), NULL
int main (int argc, char *argv[]) {
    // pole znaku bez pridelene pameti
    // (pole je ukazatelem na prvni prvek)
    char *str; 
    
    // ukazatel (zde str) obsahuje nesmyslne hodnoty
    // pokud jej neinicializujeme (nebo neni globalni)
    str = NULL; // nastaveni na prazdny ukazatel
    
    // lze i primo v deklaraci
    // char *str = NULL;
    
    // inicializovane pole 
    // (bude mu pridelena pamet delky retezce "abcd\0")
    char *zdroj = "abcd";
    
    // kopirovani pole zdroj do pole str
    // 1. zjisteni delky zdrojoveho retezce
    //    funkce strlen() vraci pocet znaku bez koncove nuly ('\0')
    int delka = strlen(zdroj);
    
    // 2. prideleni pameti o jedna vetsi pro koncovou nulu ('\0')
    str = new char[delka + 1];
    
    // 3. kopirovani
    strcpy(str, zdroj);
    
    // vypis obsahu pro srovnani (0 se nevypisuje) 
    printf("delka = %d znaku \n", delka);    
    printf("zdroj = \"%s\" \n  str = \"%s\" \n", zdroj, str);
        
    delete[] str; // uvolneni pameti
    
    return 0;
}

reference (Odkazy)
Odkaz je alternativním jménem objektu. Hlavní použití spočívá ve specifikaci návratových argumentů funkcí. Odkaz se musí inicializovat přiřazením objektu, kterému bude sloužit jako jméno (alias). Operátory poté neoperují nad odkazy, ale nad původními typy.

odkaz[ ref.cpp ]
#include <stdio.h>  // printf()
int main (int argc, char *argv[]) {
    int i = 1;    
    int& odkaz = i; //odkaz na promennou i
    printf("pred : odkaz(%d), i(%d) \n", odkaz, i);
    
    odkaz = odkaz + 10; // pricteni 10
    odkaz++;            // zvyseni o 1
    
    printf("po   : odkaz(%d), i(%d) \n", odkaz, i);
    return 0;
}

Java

reference
Proměnné objektových typů neobsahují přímo objekty, ale pouze jejich reference. Díky tomu je možné mít pro konkrétní instanci třídy více jmen. Další výhodou je předávání objektů funkcím, které je prostřednictvím referencí provedeno vždy odkazem.

JavaScript

Matlab

PHP

reference (odkaz)
Přes reference může mít obsah jedné proměnné více názvů (aliasů). Pro vytvoření reference používáme operátor &. Další užitečnou vlastností referencí je předávání proměnných odkazem u funkcí.

reference[ ref.php ]
<html>            
  <head>
    <title>Reference</title>
  </head>
  
  <body>
    <?php
      $i = 15; 
      $reference = & $i; // vytvoreni odkazu na promennou i
      
      $reference++;  // zvyseni i o 1
      
      // vypis obsahu $i pres referenci a $i (= 16)
      echo "reference($reference), i($i) <br/>";
      
      //funkce s promennou predanou odkazem (&)
      function inc(&$parametr) {
          $parametr++; //zvyseni o 1
      }
      
      inc($i); // volani funkce s parametrem $i predanym odkazem
      
      // vypis obsahu $i pres referenci a $i (= 17)
      echo "reference($reference), i($i) <br/>";
    ?>
  </body>
</html>

Kontakt
Prohlášení o dostupnosti
Tisk stránky
Autor: Václav Bubník © 2005
vbubnik@post.cz
XHTML 1.0| CSS