C++ Ukazatele s příklady
Co jsou ukazatele?
In C++, ukazatel odkazuje na proměnnou, která obsahuje adresu jiné proměnné. Stejně jako běžné proměnné mají ukazatele datový typ. Například ukazatel typu integer může obsahovat adresu proměnné typu integer. Ukazatel znakového typu může obsahovat adresu proměnné znakového typu.
Měli byste vidět ukazatel jako symbolickou reprezentaci adresy paměti. Pomocí ukazatelů mohou programy simulovat volání podle reference. Mohou také vytvářet a manipulovat s dynamickými datovými strukturami. V C++, proměnná ukazatele odkazuje na proměnnou ukazující na konkrétní adresu v paměti, na kterou ukazuje jiná proměnná.
Adresy v C++
Rozumět C++ ukazatelů, musíte pochopit, jak počítače ukládají data.
Když vytvoříte proměnnou ve vašem C++ program, je mu přidělen určitý prostor v paměti počítače. Hodnota této proměnné je uložena v přiřazeném umístění.
Chcete-li zjistit umístění v paměti počítače, kde jsou data uložena, C++ poskytuje & (referenční) operátor. Operátor vrací adresu, kterou proměnná zabírá.
Pokud je například x proměnná, &x vrátí adresu proměnné.
Syntaxe deklarace ukazatele
Prohlášení o C++ má následující syntaxi:
datatype *variable_name;
- Datový typ je základní typ ukazatele, který musí být platný C++ datový typ.
- Název proměnné by měl být název proměnné ukazatele.
- Hvězdička použitá výše pro deklaraci ukazatele je podobná hvězdičce používané k provádění operace násobení. Je to hvězdička, která označuje proměnnou jako ukazatel.
Zde je příklad platných deklarací ukazatelů v C++:
int *x; // a pointer to integer double *x; // a pointer to double float *x; // a pointer to float char *ch // a pointer to a character
Referenční operátor (&) a operátor Deference (*)
Referenční operátor (&) vrací adresu proměnné.
Operátor dereference (*) nám pomáhá získat hodnotu, která byla uložena v adrese paměti.
Například:
Pokud máme proměnnou s názvem num, uloženou v adrese 0x234 a ukládající hodnotu 28.
Referenční operátor (&) vrátí 0x234.
Operátor dereference (*) vrátí 5.
Příklad 1:
#include <iostream> using namespace std; int main() { int x = 27; int *ip; ip = &x; cout << "Value of x is : "; cout << x << endl; cout << "Value of ip is : "; cout << ip<< endl; cout << "Value of *ip is : "; cout << *ip << endl; return 0; }
Výstup:
Jak to funguje:
Zde je snímek obrazovky kódu:
Vysvětlení kódu:
- Importujte soubor záhlaví iostream. To nám umožní používat funkce definované v záhlaví souboru bez chyb.
- Zahrňte jmenný prostor std, abyste mohli používat jeho třídy bez jeho volání.
- Zavolejte funkci main(). Programová logika by měla být přidána do těla této funkce. { označuje začátek těla funkce.
- Deklarujte celočíselnou proměnnou x a přiřaďte jí hodnotu 27.
- Deklarujte proměnnou ukazatele *ip.
- Uložte adresu proměnné x do proměnné ukazatele.
- Vytiskněte nějaký text na konzoli.
- Vytiskněte hodnotu proměnné x na obrazovku.
- Vytiskněte nějaký text na konzoli.
- Vytiskněte adresu proměnné x. Hodnota adresy byla uložena v proměnné ip.
- Vytiskněte nějaký text na konzoli.
- Tisk hodnoty uložené na adrese ukazatele.
- Program by měl po úspěšném spuštění vrátit hodnotu.
- Konec těla funkce main().
Ukazatele a pole
Pole a ukazatele fungují na základě souvisejícího konceptu. Při práci s poli s ukazateli je třeba si povšimnout různých věcí. Samotný název pole označuje základní adresu pole. To znamená, že pro přiřazení adresy pole ukazateli byste neměli používat ampersand (&).
Například:
p = arr;
Výše uvedené je správné, protože arr představuje adresu polí. Zde je další příklad:
p = &arr;
Výše uvedené je nesprávné.
Pole můžeme implicitně převést na ukazatel. Například:
int arr [20]; int * ip;
Níže je platná operace:
ip = arr;
Po výše uvedené deklaraci budou ip a arr ekvivalentní a budou sdílet vlastnosti. K ip však lze přiřadit jinou adresu, ale k arr nemůžeme nic přiřadit.
Příklad 2:
Tento příklad ukazuje, jak procházet pole pomocí ukazatelů:
#include <iostream> using namespace std; int main() { int *ip; int arr[] = { 10, 34, 13, 76, 5, 46 }; ip = arr; for (int x = 0; x < 6; x++) { cout << *ip << endl; ip++; } return 0; }
Výstup:
Zde je snímek obrazovky kódu:
Vysvětlení kódu:
- Deklarujte celočíselnou proměnnou ip.
- Deklarujte pole s názvem arr a uložte do něj 6 celých čísel.
- Přiřadit arr k ip. IP a arr se stanou ekvivalentními.
- Vytvořte smyčku for. Proměnná smyčky x byla vytvořena pro iteraci prvků pole od indexu 0 do 5.
- Vytiskněte hodnoty uložené na adrese IP ukazatele. Na každou iteraci bude vrácena jedna hodnota a bude provedeno celkem 6 opakování. Konec je a C++ klíčové slovo, které znamená koncový řádek. Tato akce umožňuje přesunout kurzor na další řádek po vytištění každé hodnoty. Každá hodnota bude vytištěna na samostatném řádku.
- Chcete-li přesunout ukazatel na další pozici int po každé iteraci.
- Konec smyčky for.
- Po úspěšném provedení musí program něco vrátit.
- Konec těla funkce main().
Ukazatel NULL
Pokud neexistuje přesná adresa, která má být přiřazena, lze proměnné ukazatele přiřadit hodnotu NULL. Mělo by to být provedeno během prohlášení. Takový ukazatel je známý jako nulový ukazatel. Jeho hodnota je nula a je definována v mnoha standardních knihovnách, jako je iostream.
Příklad 3:
#include <iostream> using namespace std; int main() { int *ip = NULL; cout << "Value of ip is: " << ip; return 0; }
Výstup:
Zde je snímek obrazovky kódu:
Vysvětlení kódu:
- Deklarujte ukazatelovou proměnnou ip a přiřaďte jí hodnotu NULL.
- Vytisknout hodnotu proměnné ip ukazatele vedle textu na konzole.
- Program musí po úspěšném dokončení vrátit hodnotu.
- Konec těla funkce main().
Ukazatele proměnných
S C++, můžete manipulovat s daty přímo z paměti počítače.
Paměťový prostor lze libovolně přiřadit nebo znovu přiřadit. To umožňují proměnné ukazatele.
Proměnné ukazatele ukazují na konkrétní adresu v paměti počítače, na kterou ukazuje jiná proměnná.
Dá se deklarovat následovně:
int *p;
Nebo,
int* p;
V příkladu you jsme deklarovali proměnnou ukazatele p.
Bude obsahovat adresu paměti.
Hvězdička je operátor dereference, který znamená ukazatel na.
Ukazatel p ukazuje na celočíselnou hodnotu v adrese paměti.
Příklad 4:
#include <iostream> using namespace std; int main() { int *p, x = 30; p = &x; cout << "Value of x is: " << *p; return 0; }
Výstup:
Zde je snímek obrazovky kódu:
Vysvětlení kódu:
- Deklarujte ukazatelovou proměnnou p a proměnnou x s hodnotou 30.
- Přiřaďte adresu proměnné x k p.
- Vytiskněte hodnotu proměnné ukazatele p vedle textu na konzole.
- Program musí po úspěšném dokončení vrátit hodnotu.
- Konec těla funkce main().
Aplikace ukazatelů
Funkce v C++ může vrátit pouze jednu hodnotu. Dále jsou všechny proměnné deklarované ve funkci alokovány v zásobníku volání funkce. Jakmile se funkce vrátí, všechny proměnné zásobníku jsou zničeny.
Argumenty funkce jsou předávány hodnotou a jakákoliv úprava proměnných nemění hodnotu skutečných předávaných proměnných. Následující příklad pomáhá ilustrovat tento koncept: -
Příklad 5:
#include <iostream> using namespace std; void test(int*, int*); int main() { int a = 5, b = 5; cout << "Before changing:" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; test(&a, &b); cout << "\nAfter changing" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; return 0; } void test(int* n1, int* n2) { *n1 = 10; *n2 = 11; }
Výstup:
Zde je snímek obrazovky kódu:
Vysvětlení kódu:
- Vytvořte prototyp funkce s názvem test, který bude mít dva celočíselné parametry.
- Zavolejte funkci main(). Do jeho těla přidáme logiku programu.
- Deklarujte dvě celočíselné proměnné a a b, každou s hodnotou 5.
- Vytiskněte nějaký text na konzoli. Endl (koncový řádek) přesune kurzor a začne tisknout na dalším řádku.
- Vytiskněte hodnotu proměnné a na konzole vedle jiného textu. Endl (koncový řádek) přesune kurzor a začne tisknout na dalším řádku.
- Vytiskněte hodnotu proměnné b na konzole vedle jiného textu. Endl (koncový řádek) přesune kurzor a začne tisknout na dalším řádku.
- Vytvořte funkci s názvem test(), která přebírá adresy proměnných aab jako parametry.
- Vytiskněte nějaký text na konzoli. \n před vytištěním textu vytvoří nový prázdný řádek. Endl (koncový řádek) přesune kurzor tak, aby se začal tisknout na dalším řádku po vytištění textu.
- Vytiskněte hodnotu proměnné a na konzole vedle jiného textu. Endl (koncový řádek) přesune kurzor a začne tisknout na dalším řádku.
- Vytiskněte hodnotu proměnné b na konzole vedle jiného textu. Endl (koncový řádek) přesune kurzor a začne tisknout na dalším řádku.
- Program musí po úspěšném dokončení vrátit hodnotu.
- Konec těla funkce main().
- Definování funkce test(). Funkce by měla mít dvě celočíselné proměnné *n1 a *n2.
- Přiřazení ukazatelové proměnné *n1 hodnotu 10.
- Přiřazení ukazatelové proměnné *n2 hodnotu 11.
- Konec těla funkce test().
I když jsou proměnné aab v rámci funkčního testu přiřazeny nové hodnoty, jakmile je volání funkce dokončeno, totéž se neprojeví ve vnější funkci main.
Použití ukazatelů jako argumentů funkce pomáhá předat skutečnou adresu proměnné ve funkci a všechny změny provedené na proměnné se projeví ve vnější funkci.
Ve výše uvedeném případě má funkce 'test' adresu proměnných 'a' a 'b.' Tyto dvě proměnné jsou přímo přístupné z funkce 'test', a proto se jakákoli změna provedená v těchto proměnných projeví ve funkci volajícího 'main.
Výhody použití ukazatelů
Zde jsou výhody/výhody používání ukazatelů
- Ukazatele jsou proměnné, které ukládají adresu ostatních proměnné v C++.
- Více než jednu proměnnou lze upravit a vrátit funkcí pomocí ukazatelů.
- Paměť lze dynamicky přidělovat a oddělovat pomocí ukazatelů.
- Ukazatele pomáhají zjednodušit složitost programu.
- Rychlost provádění programu se zlepšuje pomocí ukazatelů.
Shrnutí
- Ukazatel odkazuje na proměnnou držící adresu jiné proměnné.
- Každý ukazatel má platný datový typ.
- Ukazatel je symbolická reprezentace adresy paměti.
- Ukazatele umožňují programům simulovat volání po referenci a vytvářet a manipulovat s dynamickými datovými strukturami.
- Pole a ukazatele používají související koncept.
- Název pole označuje základ pole.
- Pokud chcete přiřadit adresu pole k ukazateli, nepoužívejte ampersand (&).
- Pokud neexistuje žádná konkrétní adresa k přiřazení proměnné ukazatele, přiřaďte jí hodnotu NULL.