I'm new to Ada.
I saw this question, but mine is a little different:
type A is record
x : integer;
y : integer;
end record;
procedure P1 is
temp : A;
begin
temp.x := 100;
P2(temp);
if temp.x = 100 then
Ada.Text_IO.Put_Line("true");
else
Ada.Text_IO.Put_Line("false");
end if;
end One;
procedure P2 (arg1 : out A) is
begin
arg1.y := 200;
end P2;
My question is with the "out" parameter in P2: will other parts of a composite type be undefined if P2 didn't explicitly set them. In other words, if P1 is called, would the output be definitely true or false? Or maybe ambiguous?
This link talks about "default initialization", but my example above doesn't have it explicitly (on purpose).
Safety is preserved by ensuring that a subcomponent does not become
"deinitialized" by being passed as an out parameter. If any subcomponent
of a type passed by copy has default initialization, then the whole
object is copied in at the start of the call so that the value of such a
subcomponent is not lost as a result of a subprogram call during which
no assignment is made to the subcomponent. But in practice records are
usually passed by reference anyway.
The quoted passage, §6.1.1 Out Parameters, may be easier to understand after reviewing §6.2 Formal Parameter Modes. For a parameter of type A
, "it is unspecified whether the parameter is passed by copy or by reference." The implementation is free to choose. In either case, the x
component of a value of type A
is unchanged by P2
. P1
prints "true" because you have given the x
component a value of 100
explicitly prior to calling P2
. Absent initialization, default or otherwise, temp.x
contains whatever bits were in memory when making room for temp
, typically by adjusting a stack pointer.
As an exercise, try omitting the initialization and examining the value:
--temp.x := 100;
P2(temp);
if temp.x = 100 then
Ada.Text_IO.Put_Line("true");
else
Ada.Text_IO.Put_Line("false");
end if;
Ada.Text_IO.Put_Line(temp.x'Img & temp.y'Img);
On my implementation, the predicate fails and temp.x
contains garbage.
false
1934820168 200
Using a default_expression with the record components avoids the risk of overlooking the initialization.
type A is record
x : integer := 0;
y : integer := 0;
end record;
If it is compiler dependent, then is using
in out
the only sure way to make sure it works.
Absent default initialization, yes. As noted in §6.1 Parameter and Result Mechanism, "In Ada 95 it is not erroneous to depend on the parameter passing mechanism (by-reference versus by-copy) for those types that allow both, though it is nonportable." Because arg1
in P2
is an out
parameter that may be passed by copy—and it is neither an access type nor a composite type with discriminants nor a type having an implicit initial value—§6.4.1 Parameter Associations makes clear that "the formal parameter is uninitialized." In contrast, for an in out
parameter, "the value of the actual parameter is…assigned to the formal."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With