Access Types (Pointers) & Allocators
Declare pool-specific and general access types, allocate objects with new (initialized allocators), dereference with .all and implicit dereference, use aliased objects with 'Access, access-to-constant, null and not null exclusions, and understand access equality vs value equality.
Ada calls pointers access types, and it makes them much safer than raw C pointers: each access type is strongly typed, access values default to null, dereferencing null raises Constraint_Error instead of crashing, you cannot do pointer arithmetic, and you cannot take the address of an ordinary variable unless it is explicitly marked aliased. Many Ada programs need few or no access types at all — arrays, records, unconstrained types and containers cover most needs.
Pool-Specific Access Types and Allocators
'type Point_Ptr is access Point;' declares a pool-specific access type: its values can only designate objects created by an allocator for that type. 'new Point' allocates a default-initialized object; 'new Point'(1, 2)' allocates and initializes it with a qualified expression. P.all denotes the whole designated object; for records and arrays, components are reached by implicit dereference (P.X instead of P.all.X). Access values are default-initialized to null — there are no uninitialized pointers.
• type T_Ptr is access T; — pool-specific. • new T or new T'(value) allocates. • P.all = the object; P.X = implicit dereference. • Access objects start as null.
General Access Types and aliased
'type Int_Ptr is access all Integer;' is a general access type: its values may also designate declared objects, but only objects marked 'aliased' (Count : aliased Integer). X'Access creates the access value. 'access constant' gives a read-only view and can designate aliased constants. The 'aliased' keyword documents that something may be reached through a pointer, which is vital for reasoning about side effects and for optimization.
• access all T — may point to aliased declared objects via 'Access. • access constant T — read-only view. • Only aliased objects can be pointed to.
null, not null, and Equality
Dereferencing null raises Constraint_Error. A null exclusion — 'not null Point_Ptr' on a subtype, parameter, component or object — moves the check to where the value enters, documents the intent, and lets the compiler omit checks inside. P = Q compares access values (do they designate the same object?), while P.all = Q.all compares the designated values. Assigning P to Q copies the pointer, creating two names for one object (aliasing); 'new Point'(P.all)' copies the object.
• null dereference → Constraint_Error. • not null T_Ptr — checks at the boundary. • P = Q: same object? P.all = Q.all: same value? • No pointer arithmetic in Ada.
Code Examples
P is a constant access value, but the object it designates can still change. Q := P shares the object; Q := new Point'(P.all) copies it. Count is changed through IP. GNAT warns at compile time that passing null to Show's not null parameter will raise Constraint_Error — and it does. Output: P.all = ( 1, 2 ) P after changes through Q = ( 5, 7 ) P = Q (same object)? TRUE P.all = Q.all (same value)? TRUE After copying: P.X = 5, Q.X = 0 Count = 11, CIP.all = 99 Dereferencing null raised Constraint_Error Passing null to a not null parameter raised Constraint_Error
X : Integer := 5; P : Int_Ptr := X'Access;
X : aliased Integer := 5; P : Int_Ptr := X'Access;
Only aliased objects may be designated by general access values.
if P = Q then -- intending to compare contents if P.all = Q.all then
= on access values compares identity, not contents.
procedure Show (V: Point_Ptr) is begin if V /= null then... -- checks everywhere procedure Show (V: not null Point_Ptr) is
A null exclusion documents the requirement and checks once at the call.
What is the default value of an access object? A. Random B. null C. A new object D. 0
What happens when you dereference null? A. Segmentation fault B. Constraint_Error C. Returns 0 D. Undefined behavior
Which objects can 'X'Access' be applied to? A. Any variable B. Only aliased objects (for general access types) C. Only constants D. Only heap objects
After Q := P, then Q.Y := 7, what is P.Y? A. Unchanged B. 7 C. null D. Compile error
B. 7 — P and Q designate the same object (verified).
Trace the access-type example.
Real output: P.all = ( 1, 2 ) P after changes through Q = ( 5, 7 ) P = Q (same object)? TRUE P.all = Q.all (same value)? TRUE After copying: P.X = 5, Q.X = 0 Count = 11, CIP.all = 99 Dereferencing null raised Constraint_Error Passing null to a not null parameter raised Constraint_Error
with Ada.Text_IO; use Ada.Text_IO;
procedure L30_Access is
type Point is record
X, Y : Integer;
end record;
-- Pool-specific access type: may only designate objects created by "new"
type Point_Ptr is access Point;
-- General access types: may also designate aliased declared objects
type Int_Ptr is access all Integer;
type Const_Int_Ptr is access constant Integer; -- read-only view
subtype Valid_Point_Ptr is not null Point_Ptr; -- null excluded
P : constant Point_Ptr := new Point'(1, 2); -- allocator with initial value
Q : Point_Ptr; -- access objects default to null
Count : aliased Integer := 10; -- aliased: 'Access allowed
Limit : aliased constant Integer := 99;
IP : constant Int_Ptr := Count'Access;
CIP : constant Const_Int_Ptr := Limit'Access;
procedure Show (Label : String; V : Valid_Point_Ptr) is
begin
Put_Line (Label & " = (" & Integer'Image (V.X) & "," & Integer'Image (V.Y) & " )");
end Show;
begin
Show ("P.all", P);
P.X := 5; -- implicit dereference for components
Q := P; --
…