Ukazovatele sú symbolické reprezentácie adries. Umožňujú programom simulovať volanie po referencii, ako aj vytvárať a manipulovať s dynamickými dátovými štruktúrami. Iterácia prvkov v poliach alebo iných dátových štruktúrach je jedným z hlavných použití ukazovateľov.
Adresa premennej, s ktorou pracujete, je priradená k premennej ukazovateľa, ktorá ukazuje na rovnaký typ údajov (napríklad int alebo reťazec).
java double to string
Syntax:
datatype *var_name; int *ptr; // ptr can point to an address which holds int data>

Ako používať ukazovateľ?
- Definujte premennú ukazovateľa
- Priradenie adresy premennej k ukazovateľu pomocou unárneho operátora (&), ktorý vráti adresu tejto premennej.
- Prístup k hodnote uloženej v adrese pomocou unárneho operátora (*), ktorý vráti hodnotu premennej umiestnenej na adrese určenej jej operandom.
Dôvod, prečo spájame dátový typ s ukazovateľom, je že vie, v koľkých bajtoch sú dáta uložené . Keď zvyšujeme ukazovateľ, zväčšujeme ukazovateľ o veľkosť typu údajov, na ktorý ukazuje.

// C++ program to illustrate Pointers #include using namespace std; void geeks() { int var = 20; // declare pointer variable int* ptr; // note that data type of ptr and var must be same ptr = &var; // assign the address of a variable to a pointer cout << 'Value at ptr = ' << ptr << '
'; cout << 'Value at var = ' << var << '
'; cout << 'Value at *ptr = ' << *ptr << '
'; } // Driver program int main() { geeks(); return 0; }>
Výkon
Value at ptr = 0x7ffe454c08cc Value at var = 20 Value at *ptr = 20>
Referencie a ukazovatele
Existujú 3 spôsoby, ako odovzdať argumenty C++ funkcii:
- Call-By-Value
- Call-by-Reference s argumentom ukazovateľa
- Call-by-Reference s referenčným argumentom
// C++ program to illustrate call-by-methods #include using namespace std; // Pass-by-Value int square1(int n) { // Address of n in square1() is not the same as n1 in // main() cout << 'address of n1 in square1(): ' << &n << '
'; // clone modified inside the function n *= n; return n; } // Pass-by-Reference with Pointer Arguments void square2(int* n) { // Address of n in square2() is the same as n2 in main() cout << 'address of n2 in square2(): ' << n << '
'; // Explicit de-referencing to get the value pointed-to *n *= *n; } // Pass-by-Reference with Reference Arguments void square3(int& n) { // Address of n in square3() is the same as n3 in main() cout << 'address of n3 in square3(): ' << &n << '
'; // Implicit de-referencing (without '*') n *= n; } void geeks() { // Call-by-Value int n1 = 8; cout << 'address of n1 in main(): ' << &n1 << '
'; cout << 'Square of n1: ' << square1(n1) << '
'; cout << 'No change in n1: ' << n1 << '
'; // Call-by-Reference with Pointer Arguments int n2 = 8; cout << 'address of n2 in main(): ' << &n2 << '
'; square2(&n2); cout << 'Square of n2: ' << n2 << '
'; cout << 'Change reflected in n2: ' << n2 << '
'; // Call-by-Reference with Reference Arguments int n3 = 8; cout << 'address of n3 in main(): ' << &n3 << '
'; square3(n3); cout << 'Square of n3: ' << n3 << '
'; cout << 'Change reflected in n3: ' << n3 << '
'; } // Driver program int main() { geeks(); }>
Výkon
address of n1 in main(): 0x7fffa7e2de64 address of n1 in square1(): 0x7fffa7e2de4c Square of n1: 64 No change in n1: 8 address of n2 in main(): 0x7fffa7e2de68 address of n2 in square2(): 0x7fffa7e2de68 Square of n2: 64 Change reflected in n2: 64 address of n3 in main(): 0x7fffa7e2de6c address of n3 in square3(): 0x7fffa7e2de6c Square of n3: 64 Change reflected in n3: 64>
V C++ sa štandardne argumenty odovzdávajú podľa hodnoty a zmeny vykonané vo volanej funkcii sa neprejavia v odovzdávanej premennej. Zmeny sa urobia do klonu vytvoreného volanou funkciou. Ak chcete upraviť originálnu kópiu priamo (najmä pri odovzdávaní veľkého objektu alebo poľa) a/alebo sa vyhnúť réžii pri klonovaní, používame pass-by-reference. Pass-by-Reference with Reference Arguments nevyžaduje žiadnu neohrabanú syntax pre odkazovanie a dereferencovanie.
- Ukazovatele funkcií v C
- Ukazovateľ na funkciu
Názov poľa ako ukazovatele
An pole name obsahuje adresu prvého prvku poľa, ktorý funguje ako konštantný ukazovateľ. To znamená, že adresu uloženú v názve poľa nemožno zmeniť. Napríklad, ak máme pole s názvom val then val a &val[0] možno použiť zameniteľne.
C++ // C++ program to illustrate Array Name as Pointers #include using namespace std; void geeks() { // Declare an array int val[3] = { 5, 10, 20 }; // declare pointer variable int* ptr; // Assign the address of val[0] to ptr // We can use ptr=&val[0];(both are same) ptr = val; cout << 'Elements of the array are: '; cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2]; } // Driver program int main() { geeks(); }>
Výkon
Elements of the array are: 5 10 20>

Ak sa do funkcie odošle ukazovateľ ptr ako argument, k poli val možno pristupovať podobným spôsobom. Ukazovateľ vs pole
Výrazy ukazovateľa a aritmetika ukazovateľa
Obmedzená sada aritmetika operácie možno vykonávať na ukazovateľoch, ktoré sú:
koľko miliónov je v miliarde
- zvýšené ( ++ )
- znížené ( — )
- k ukazovateľu možno pridať celé číslo ( + alebo += )
- celé číslo možno odpočítať od ukazovateľa ( – alebo -= )
- rozdiel medzi dvoma ukazovateľmi (p1-p2)
( Poznámka: Aritmetika ukazovateľa nemá zmysel, pokiaľ sa nevykonáva na poli.)
C++ // C++ program to illustrate Pointer Arithmetic #include using namespace std; void geeks() { // Declare an array int v[3] = { 10, 100, 200 }; // declare pointer variable int* ptr; // Assign the address of v[0] to ptr ptr = v; for (int i = 0; i < 3; i++) { cout << 'Value at ptr = ' << ptr << '
'; cout << 'Value at *ptr = ' << *ptr << '
'; // Increment pointer ptr by 1 ptr++; } } // Driver program int main() { geeks(); }>
Výkon
Value at ptr = 0x7ffe5a2d8060 Value at *ptr = 10 Value at ptr = 0x7ffe5a2d8064 Value at *ptr = 100 Value at ptr = 0x7ffe5a2d8068 Value at *ptr = 200>

Pokročilá notácia ukazovateľa
Zvážte notáciu ukazovateľa pre dvojrozmerné číselné polia. zvážte nasledujúce vyhlásenie
int nums[2][3] = { { 16, 18, 20 }, { 25, 26, 27 } };>
Vo všeobecnosti je nums[ i ][ j ] ekvivalentom *(*(nums+i)+j)

Ukazovatele a reťazcové literály
Reťazcové literály sú polia obsahujúce sekvencie znakov ukončené nulou. Reťazcové literály sú polia typu znak plus ukončovací znak null, pričom každý z prvkov je typu const char (pretože znaky reťazca nemožno upravovať).
>
Toto deklaruje pole s doslovnou reprezentáciou pre geek a potom sa ukazovateľ na jeho prvý prvok priradí k ptr. Ak si predstavíme, že geek je uložený na pamäťových miestach, ktoré začínajú na adrese 1800, môžeme predchádzajúcu deklaráciu reprezentovať ako:

Keďže sa ukazovatele a polia správajú vo výrazoch rovnakým spôsobom, ptr možno použiť na prístup k znakom reťazcového literálu. Napríklad:
char ptr = 0; char x = *(ptr+3); char y = ptr[3];>
Tu x aj y obsahujú k uložené na 1803 (1800+3).
sqrt java matematika
Ukazovatele na ukazovatele
V C++ môžeme vytvoriť ukazovateľ na ukazovateľ, ktorý zase môže ukazovať na údaje alebo iný ukazovateľ. Syntax jednoducho vyžaduje unárny operátor (*) pre každú úroveň nepriameho smeru pri deklarovaní ukazovateľa.
char a; char *b; char ** c; a = ’g’; b = &a; c = &b;>
Tu b ukazuje na znak, ktorý ukladá „g“ a c ukazuje na ukazovateľ b.
Void Ukazovatele
Toto je špeciálny typ ukazovateľa dostupný v C++, ktorý predstavuje absenciu typu. Neplatné ukazovatele sú ukazovatele, ktoré ukazujú na hodnotu, ktorá nemá typ (a teda aj neurčenú dĺžku a neurčené vlastnosti dereferencovania). To znamená, že ukazovatele neplatnosti majú veľkú flexibilitu, pretože môžu ukazovať na akýkoľvek typ údajov. Táto flexibilita sa oplatí. Tieto ukazovatele nemožno priamo dereferencovať. Pred dereferencovaním sa musia najprv transformovať na nejaký iný typ ukazovateľa, ktorý ukazuje na konkrétny typ údajov.
C++ // C++ program to illustrate Void Pointer #include using namespace std; void increase(void* data, int ptrsize) { if (ptrsize == sizeof(char)) { char* ptrchar; // Typecast data to a char pointer ptrchar = (char*)data; // Increase the char stored at *ptrchar by 1 (*ptrchar)++; cout << '*data points to a char' << '
'; } else if (ptrsize == sizeof(int)) { int* ptrint; // Typecast data to a int pointer ptrint = (int*)data; // Increase the int stored at *ptrchar by 1 (*ptrint)++; cout << '*data points to an int' << '
'; } } void geek() { // Declare a character char c = 'x'; // Declare an integer int i = 10; // Call increase function using a char and int address // respectively increase(&c, sizeof(c)); cout << 'The new value of c is: ' << c << '
'; increase(&i, sizeof(i)); cout << 'The new value of i is: ' << i << '
'; } // Driver program int main() { geek(); }>
Výkon
*data points to a char The new value of c is: y *data points to an int The new value of i is: 11>
Neplatné ukazovatele
Ukazovateľ by mal ukazovať na platnú adresu, ale nie nevyhnutne na platné prvky (ako v prípade polí). Tieto sa nazývajú neplatné ukazovatele. Neinicializované ukazovatele sú tiež neplatné ukazovatele.
int *ptr1; int arr[10]; int *ptr2 = arr+20;>
Tu je ptr1 neinicializovaný, takže sa stane neplatným ukazovateľom a ptr2 je mimo hraníc arr, takže sa tiež stane neplatným ukazovateľom. (Poznámka: neplatné ukazovatele nemusia nevyhnutne spôsobovať chyby kompilácie)
počítač vynájdený rok
NULL ukazovatele
A nulový ukazovateľ je ukazovateľ, ktorý nikam neukazuje a nie je to len neplatná adresa. Nasledujú 2 metódy na priradenie ukazovateľa ako NULL;
int *ptr1 = 0; int *ptr2 = NULL;>
Výhody ukazovateľov
- Ukazovatele redukujú kód a zlepšujú výkon. Používajú sa na získanie reťazcov, stromov, polí, štruktúr a funkcií.
- Ukazovatele nám umožňujú vrátiť viacero hodnôt z funkcií.
- Okrem toho nám ukazovatele umožňujú prístup k miestu pamäte v pamäti počítača.
Súvisiace články:
- Nepriehľadný ukazovateľ
- Blízke, vzdialené a obrovské ukazovatele
Kvízy:
- Základy ukazovateľa
- Pokročilý ukazovateľ