Ukazatel (počítačové programování)
AdaEdit
Ada je jazyk se silným typem, kde jsou zadávány všechny ukazatele a jsou povoleny pouze převody bezpečného typu. Všechny ukazatele jsou ve výchozím nastavení inicializovány na null
a jakýkoli pokus o přístup k datům pomocí null
ukazatele způsobí vyvolání výjimky. Ukazatele v Adě se nazývají typy přístupu. Ada 83 nepovolila aritmetiku na typech přístupu (ačkoli mnoho prodejců překladačů ji poskytlo jako nestandardní funkci), ale Ada 95 podporuje „bezpečnou“ aritmetiku na typy přístupu prostřednictvím balíčku System.Storage_Elements
.
BASICEdit
Několik starých verzí jazyka BASIC pro platformu Windows mělo podporu STRPTR () pro vrácení adresy řetězce a pro VARPTR () pro vrácení adresy proměnná. Visual Basic 5 měl také podporu pro OBJPTR () pro vrácení adresy rozhraní objektu a pro operátor ADDRESSOF pro vrácení adresy funkce. Typy všech z nich jsou celá čísla, ale jejich hodnoty jsou ekvivalentní ty, které drží typy ukazatelů.
Novější dialekty jazyka BASIC, jako je FreeBASIC nebo BlitzMax, však mají vyčerpávající implementaci ukazatelů. Ve FreeBASIC je aritmetika ANY
ukazatelů ( ekvivalentní C „s void*
) se zachází, jako by ukazatel ANY
měl šířku bajtu. Ukazatele ANY
nelze dereferencovat, jako je tomu v C. Také vržení mezi ANY
a ukazateli jakéhokoli jiného typu nebude generovat žádná varování.
dim as integer f = 257dim as any ptr g = @fdim as integer ptr i = gassert(*i = 257)assert( (g + 4) = (@f + 1) )
Úpravy C a C ++
V ukazatelích C a C ++ jsou proměnné, které ukládají adresy a může mít hodnotu null. Každý ukazatel má typ, na který ukazuje, ale lze jej libovolně vrhat mezi typy ukazatelů (ale ne mezi ukazatelem na funkci a ukazatelem na objekt). Speciální typ ukazatele nazývaný „void pointer“ umožňuje ukazovat na libovolné -funkce) objekt, ale je omezen skutečností, že jej nelze dereferencovat přímo (bude seslán). Samotnou adresu lze často přímo manipulovat vržením ukazatele na az integrálního typu dostatečné velikosti, ačkoli výsledky jsou definovány implementací a mohou skutečně způsobit nedefinované chování; zatímco dřívější standardy C neměly integrální typ, u kterého bylo zaručeno, že bude dostatečně velký, C99 specifikuje uintptr_t
typedef název definovaný v <stdint.h>
, ale implementace to nemusí poskytovat.
C ++ plně podporuje C ukazatele a C typcasting. Podporuje také novou skupinu operátorů vysílání typu, která pomáhá zachytit některé nechtěné nebezpečné obsazení v době kompilace. Od C ++ 11 poskytuje standardní knihovna C ++ také inteligentní ukazatele (unique_ptr
, shared_ptr
a weak_ptr
), které lze v některých situacích použít jako bezpečnější alternativu k primitivním ukazatelům C. C ++ také podporuje jinou formu odkazu, zcela odlišnou od ukazatele, nazvanou jednoduše odkaz nebo typ odkazu.
Aritmetika ukazatele, tj. Schopnost upravit cílovou adresu ukazatele pomocí aritmetických operací (jako i srovnání velikosti), je jazykovým standardem omezeno na to, aby zůstalo v mezích jediného objektu pole (nebo těsně za ním), a jinak vyvolá nedefinované chování. Přidání nebo odečtení od ukazatele jej posune o násobek velikosti Například jeho přidání 1 k ukazateli na 4bajtové celočíselné hodnoty zvýší adresu ukazatele na bajt ukazatele o 4. To má za následek zvýšení ukazatele tak, aby ukazoval na další prvek v sousedícím pole celých čísel – což je často zamýšlený výsledek. Pointer arithmetic cannot be performed on void
pointers because the void type has no size, and therefore the identified address cannot be added to, though gcc and other compilers will perform byte arithmetic on void*
jako nestandardní rozšíření, zachází s ním, jako by to bylo char *
.
Aritmetika ukazatele poskytuje programátorovi jediný způsob řešení různých typů: přidání a odečtení počtu požadovaných prvků namísto skutečného posunutí v bajtech. (Aritmetika ukazatele s char *
ukazateli používá posunutí bajtů, protože sizeof(char)
je podle definice 1.) Definice C zejména výslovně deklaruje, že syntaxe a
, což je n
-tý prvek pole a
, je ekvivalentní to *(a + n)
, což je obsah prvku, na který ukazuje a + n
. To znamená, že n
je ekvivalentní s a
a lze psát např. a
nebo 3
stejně dobře pro přístup ke čtvrtému prvku pole a
.
I když je ukazatel aritmetický výkonný, může být zdrojem počítačových chyb. Má tendenci zmást začínající programátory a nutit je do různých kontextů: výraz může být obyčejný aritmetický nebo ukazatel aritmetický a někdy je snadné zaměnit jeden za druhý. V reakci na to mnoho moderních počítačových počítačů na vysoké úrovni (například Java) neumožňuje přímý přístup do paměti pomocí adres. Bezpečný C dialekt Cyclone také řeší mnoho problémů s ukazateli. Další diskuse najdete v programovacím jazyce C.
Ukazatel void
nebo void*
je podporován v ANSI C a C ++ jako obecný typ ukazatele. Ukazatel na void
může uložit adresu libovolného objektu (nikoli funkce) a v C je při přiřazení implicitně převeden na jakýkoli jiný typ ukazatele na objekt, ale musí být explicitně obsazen if dereferenced.K & RC použil char*
pro účel „typ-agnostický ukazatel“ (před ANSI C).
C ++ neumožňuje implicitní převod void*
na jiné typy ukazatelů, a to ani v přiřazeních. Toto bylo konstrukční rozhodnutí, jak se vyhnout neopatrným a dokonce nechtěným castingům, ačkoli většina kompilátorů vydává pouze varování , nikoli chyby, když se setkáte s jinými castingy.
V C ++ neexistuje void&
(odkaz na void), který by doplňoval void*
(ukazatel na void), protože odkazy se chovají jako aliasy proměnných, na které odkazují, a nikdy nemůže existovat proměnná, jejíž typ je void
.
Přehled syntaxe deklarace ukazateleUpravit
Tato deklarace ukazatele c přes většinu variant deklarací ukazatele. Samozřejmě je možné mít trojité ukazatele, ale hlavní principy trojitého ukazatele již existují v dvojitém ukazateli.
() a mají vyšší prioritu než *.
C # Edit
V programovacím jazyce C # jsou ukazatele podporovány pouze za určitých podmínek: jakýkoli blok kódu včetně ukazatelů musí být označen klíčovým slovem unsafe
. Takové bloky obvykle vyžadují ke spuštění vyšší bezpečnostní oprávnění. Syntaxe je v podstatě stejná jako v C ++ a namířená adresa může být spravovaná nebo nespravovaná paměť. Ukazatele na spravovanou paměť (jakýkoli ukazatel na spravovaný objekt) však musí být deklarovány pomocí klíčového slova fixed
, které brání sběrateli odpadků v přesunutí špičatého objektu jako součásti správy paměti, zatímco ukazatel je v rozsahu, takže udržuje adresu ukazatele platnou.
Výjimkou je použití struktury IntPtr
, což je bezpečný spravovaný ekvivalent k int*
a nevyžaduje nebezpečný kód. Tento typ se často vrací při použití metod z System.Runtime.InteropServices
, například:
.NET framework zahrnuje mnoho tříd a metod v System
a System.Runtime.InteropServices
jmenné prostory (například třída Marshal
), které převádějí typy .NET (například System.String
) do az mnoha nespravovaných typů a ukazatelů (například LPWSTR
nebo void*
) povolit komunikace s nespravovaným kódem. Většina takových metod má stejné požadavky na oprávnění zabezpečení jako nespravovaný kód, protože mohou ovlivnit libovolná místa v paměti.
COBOLEdit
Programovací jazyk COBOL podporuje ukazatele na proměnné. Primitivní nebo skupinové (záznamové) datové objekty deklarované v LINKAGE SECTION
programu jsou ze své podstaty založeny na ukazatelích, kde jedinou pamětí přidělenou v rámci programu je prostor pro adresu datové položky ( obvykle jedno paměťové slovo). Ve zdrojovém kódu programu se tyto datové položky používají jako každá jiná proměnná WORKING-STORAGE
, ale k jejich obsahu se implicitně přistupuje nepřímo prostřednictvím jejich LINKAGE
ukazatelů .
Paměťový prostor pro každý namířený datový objekt je obvykle přidělován dynamicky pomocí externích CALL
příkazů nebo pomocí integrovaných konstruktů rozšířeného jazyka, například EXEC CICS
nebo EXEC SQL
prohlášení.
Rozšířené verze COBOLu také poskytují proměnné ukazatele deklarované pomocí USAGE
doložky IS
POINTER
. Hodnoty těchto proměnných ukazatele se stanoví a upraví pomocí příkazů SET
a SET
ADDRESS
.
Některé rozšířené verze COBOLu také poskytují PROCEDURE-POINTER
proměnné, které jsou schopné ukládat adresy spustitelného kódu.
PL / IEdit
Jazyk PL / I poskytuje plnou podporu pro ukazatele na všechny datové typy (včetně ukazatelů na struktury), rekurzi, multitasking, zpracování řetězců a rozsáhlé integrované funkce.PL / Byl jsem docela skok vpřed ve srovnání s programovacími jazyky své doby. Ukazatele PL / I jsou netypické, a proto není pro dereferencování nebo přiřazování ukazatele vyžadován žádný casting. Syntaxe deklarace pro ukazatel je DECLARE xxx POINTER;
, která deklaruje ukazatel s názvem „xxx“. Ukazatele se používají s BASED
proměnnými. Založenou proměnnou lze deklarovat pomocí výchozího lokátoru (DECLARE xxx BASED(ppp);
nebo bez (DECLARE xxx BASED;
), kde xxx je založená proměnná, kterou může být proměnná prvku, struktura nebo pole a výchozí ukazatel je ppp). Taková proměnná může být adresa bez explicitního odkazu na ukazatel (xxx=1;
), nebo může být adresována s explicitním odkazem na výchozí vyhledávač (ppp) nebo na jakýkoli jiný ukazatel (qqq->xxx=1;
).
Aritmetika ukazatele není součástí standardu PL / I, ale mnoho překladačů umožňuje výrazy ve tvaru ptr = ptr±expression
. IBM PL / I má také integrovanou funkci PTRADD
pro provádění aritmetiky. Aritmetika ukazatele se vždy provádí v bajtech.
Kompilátory IBM Enterprise PL / I mají nová forma ukazatele s názvem HANDLE
.
DEdit
Programovací jazyk D je derivátem C a C ++, který plně podporuje C ukazatele a typcasting C.
EiffelEdit
Objektově orientovaný jazyk Eiffel využívá hodnotovou a referenční sémantiku bez aritmetiky ukazatele. Přesto jsou k dispozici třídy ukazatelů. Nabízejí aritmetiku ukazatele, typování, explicit správa paměti, int erfacing s ne-Eiffelovým softwarem a dalšími funkcemi.
FortranEdit
Fortran-90 představil funkci silně typovaného ukazatele. Ukazatele Fortran obsahují více než jen jednoduchou adresu paměti. Také zapouzdřují dolní a horní mez dimenzí pole, kroky (například pro podporu libovolných částí pole) a další metadata. Operátor přidružení =>
se používá k přidružení POINTER
k proměnné, která má TARGET
atribut. Příkaz Fortran-90 ALLOCATE
lze také použít k přidružení ukazatele k bloku paměti. Například následující kód lze použít k definování a vytvoření struktury propojeného seznamu:
Fortran-2003 přidává podporu pro ukazatele procedur. Jako součást funkce C Interoperability podporuje Fortran-2003 vnitřní funkce pro převod ukazatelů ve stylu C na ukazatele Fortran a zpět.
GoEdit
Go má ukazatele. Jeho syntaxe deklarace je ekvivalentní syntaxi C, ale byla napsána naopak, končící typem. Na rozdíl od C má Go odpadky a neumožňuje aritmetiku ukazatele. Referenční typy, jako v C ++, neexistují. Některé vestavěné typy, jako jsou mapy a kanály, jsou označeny rámečkem (tj. Interně se jedná o ukazatele na proměnlivé struktury) a jsou inicializovány pomocí funkce make
. V přístupu ke sjednocené syntaxi mezi ukazateli a ukazateli, u kterých nebyl použit ukazatel (->
): operátor tečky na ukazateli odkazuje na pole nebo metodu dereferencovaného objektu . Toto však funguje pouze s 1 úrovní indirection.
JavaEdit
Na rozdíl od C, C ++ nebo Pascal neexistuje v Javě žádná explicitní reprezentace ukazatelů. Místo toho jsou složitější datové struktury, jako jsou objekty a pole, implementovány pomocí odkazů. Jazyk neposkytuje žádné explicitní operátory manipulace s ukazatelem. Stále je možné, aby se kód pokusil dereferovat nulový odkaz (nulový ukazatel), což však má za následek vyvolání výjimky za běhu. Prostor obsazený neodkázanými paměťovými objekty je automaticky obnoven sběrem odpadu za běhu.
Modula-2Edit
Ukazatele jsou implementovány stejně jako v Pascalu, stejně jako VAR
parametry při volání procedury. Modula-2 je ještě silnější než Pascal a má méně způsobů, jak uniknout typovému systému. Některé z variant Modula-2 (například Modula-3) zahrnují sběr odpadků.
OberonEdit
Stejně jako u Modula-2 jsou k dispozici ukazatele. Existuje stále méně způsobů, jak se vyhnout typovému systému, a tak je Oberon a jeho varianty stále bezpečnější, pokud jde o ukazatele, než Modula-2 nebo jeho varianty. Stejně jako u Modula-3 je sběr odpadků součástí specifikace jazyka.
PascalEdit
Na rozdíl od mnoha jazyků, které obsahují ukazatele, umožňuje standardní ISO Pascal pouze ukazatelům odkazovat na dynamicky vytvořené proměnné, které jsou anonymní a neumožňuje jim odkazovat na standardní statické nebo lokální proměnné. Nemá aritmetiku ukazatele. Ukazatele také musí mít přidružený typ a ukazatel na jeden typ není kompatibilní s ukazatelem na jiný typ (např. Ukazatel na char není kompatibilní s ukazatelem na celé číslo).To pomáhá eliminovat problémy se zabezpečením typu související s jinými implementacemi ukazatelů, zejména s těmi, které se používají pro PL / I nebo C. Rovněž odstraňuje některá rizika způsobená visícími ukazateli, ale schopnost dynamicky uvolnit odkazovaný prostor pomocí dispose
standardní postup (který má stejný účinek jako free
funkce knihovny nalezená v jazyce C) znamená, že riziko houpajících se ukazatelů nebylo zcela vyloučeno.
V některých komerčních a otevřených implementacích kompilátoru Pascal (nebo derivátů) – jako je Free Pascal, Turbo Pascal nebo Object Pascal v Embarcadero Delphi – je však ukazatel povolen odkazovat na standardní statické nebo lokální proměnné a může být přetypovat z jednoho typu ukazatele na druhý. Aritmetika ukazatele je navíc neomezená: přidání nebo odečtení od ukazatele jej posune o tento počet bajtů v obou směrech, ale pomocí Inc
nebo Dec
standardní procedury s ním posune ukazatel o velikost datového typu, na který je deklarován. Nezadaný ukazatel je k dispozici také pod názvem Pointer
, který je kompatibilní s jinými typy ukazatelů.