Tuto lekci berte jako nahlédnutí do světa ukazatelů...
Ukazatele
Pokud to s ukazateli myslíte vážně, raději šáhněte po něčem komplexnějším, protože tady se jede podle pravidla: "Dvakrát měř - jednou řeš". Naštěstí, ukazatele nepotřebujete do doby, než vás začne zajímat, zda by vaše aplikace nemohla jet rychleji, takže pro běžnou práci nejsou zapotřebí.
Zápis ukazatelů
Ukazatele jsou proměnnými, které uchovávají paměťovou adresu jiného typu. V C# mohou uchovávat jen paměťové adresy hodnotových typů. Deklarace ukazatelů:
int *p;
nebo
int* p;
Je jedno, čemu je symbol "*" blíže, funguje to naprosto stejně. Tato
deklarace nastaví ukazatel p na počátek paměťové adresy nějakého
celého čísla.
Kombinace *p se užívá k odkazu na místo v paměti, které je obsazeno p. Proto je dán její deklarací. *p může pro celá čísla vypadat následně:
*p = 5;
Tento kus kódu převede hodnotu 5 do celých čísel (integer), dle nastavení v deklaraci. Je nutné si to neplést s případem, kdy se o ukazatel nejedná:
p = 5;
Efektem je změna paměťového místa drženého p. Nikoliv změna hodnoty celého čísla nastaveného původně v deklaraci. Ve skutečnosti p ukazuje na začátek 4 bytů (rozsah typu integer) představujících v paměti umístění 5.
Další důležitý prvek pro práci s ukazateli je operátor &, který v tomto kontextu vrátí adresu proměnné, před kterou je. Příklad nastaví p, aby ukazovalo na umístění i v paměti.
int i = 5;
int *p;
p = &i;
po přidání
*p = 10;
se hodnota i změní na 10, protože i a p ukazují na to samé místo v paměti.
Dále se ukazatelé dají použít pro struktury, ukázka:
Coords x = new Coords();
Coords *y = &x;
Poté můžete pomocí ukazatele y přistupovat k nějakému veřejnému poli ze struktury x, řekněme k z, to je možné provést buď tak
(*y).z
nebo tak
y -> z.
Unsafe code (nebezpečný kód)
Jen v tomto režimu lze používat ukazatele, většinou je nutné upozornit na to, že se to chystáte použít v kompilátoru, jinak vám nahlásí chybu (v Sharpdevelopu je to v nastaveních Project Options). V tomto režimu nefunguje automatická správa paměti (garbage collection), takže to, co napácháte, byste po sobě měli i uklidit. Ukázka programu s pointery (ukazateli):
using System;
public struct Coords
{
int x;
int y;
unsafe public static void Main()
{
Coords c = new Coords();
Coords *p = &c;
{
p->y = 6;
(*p).x = 5;
}
Console.WriteLine(c.y);
Console.WriteLine(c.x);
}
}
Tady je struktura Coords deklarována uvnitř nebezpečného kódu, ale kdyby byla deklarována mimo něj, ukazatel by musel být ve struktuře fixed, ale toto není téma na malý tutoriál, ale spíše na nějakou delší kapitolu v knize a pokud umíte anglicky nebo japonsky :), můžete spoustu informací najít v MSDN. Dostanete se do ní ze stránek Microsoftu.
Ukazatele, metody a pole
Ačkoliv jsme si řekli, že ukazatele mohou sloužit jen hodnotovým typům, výjimkou jsou pole, zde je ukázka deklarace:
int[] a = {4, 5};
int *b = a;
A jak to pracuje? To si tak ukazatel b ukazuje na první typ obsazený polem a, tento typ musí být opět hodnotový. Kód níže ukazuje, že je možné procházet pole pomocí ukazatelů:
using System;
public class Tester
{
public static void Main()
{
int[] a = {4, 5};
changeVal(a);
Console.WriteLine(a[0]);
Console.WriteLine(a[1]);
}
public unsafe static void changeVal(int[] a)
{
fixed (int *b = a)
{
*b = 5;
*(b + 1) = 7;
}
}
}
A jsme u konce. Tento tutoriál je spíše informativní než naučný, vychází to také z toho, že když nechcete, tak na ukazatele nemusíte vůbec sahat. A pokud po nich zatoužíte, není problém je použít. S ukazateli se v tomto seriálu už s největší pravděpodobností nesetkáte a raději se vrhneme na něco jednoduššího, takže příště zase trošku té normální syntaxe.