2016-11-15 1 views
5

Je suis nouveau sur Ada.Ada sur le paramètre

J'ai vu ce question, mais le mien est un peu différent:

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; 

Ma question est avec le paramètre « out » dans P2: seront d'autres parties d'un type composite sont indéfinis si P2 n'a pas explicitement définissez-les. En d'autres termes, si P1 est appelée, la sortie sera-t-elle définitivement vraie ou fausse? Ou peut-être ambigu?

Cette link parle de "l'initialisation par défaut", mais mon exemple ci-dessus ne l'a pas explicitement (volontairement).

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. 

Répondre

6

Le passage cité, §6.1.1 Out Parameters, peut-être plus facile à comprendre après avoir examiné §6.2 Formal Parameter Modes. Pour un paramètre de type A, "il n'est pas spécifié si le paramètre est passé par la copie ou par la référence." L'implémentation est libre de choisir. Dans les deux cas, le composant x d'une valeur de type A est inchangé par P2. P1 affiche "true" car vous avez donné au composant x une valeur de 100 explicitement avant d'appeler P2. L'initialisation absente, par défaut ou autre, temp.x contient tous les bits qui étaient en mémoire lors de la création de place pour temp, généralement en ajustant un pointeur de pile.

En guise d'exercice, essayer d'omettre l'initialisation et l'examen de la valeur:

--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); 

sur ma mise en œuvre, le prédicat échoue et temp.x contient des ordures.

false 
1934820168 200 

L'utilisation d'un default_expression avec les composants d'enregistrement permet d'éviter le risque de passer à côté de l'initialisation.

type A is record 
    x : integer := 0; 
    y : integer := 0; 
end record; 

Si elle est dépendante compilateur, puis utilise in out le seul moyen sûr de vous assurer qu'il fonctionne.

Absence d'initialisation par défaut, oui. Comme il est indiqué dans §6.1 Parameter and Result Mechanism, « En Ada 95, il n'est pas erroneous dépendre du mécanisme de transmission des paramètres (par référence par rapport par copie) pour les types qui permettent à la fois, bien qu'il soit nonportable. » Parce que arg1 dans P2 est un paramètre qui outpeut être transmis par copie -et ce n'est ni un type d'accès, ni un type composite avec discriminants, ni un type ayant une première §6.4.1 Parameter Associations implicite à valeur indique clairement que « le paramètre formel est non initialisé. " En revanche, pour un paramètre in out, "la valeur du paramètre réel est ... affectée à la forme".

+1

Je ne suis pas sûr que ce soit un comportement spécifique au compilateur? Est-ce qu'un compilateur capable de passer par copie se comporterait de la même manière?J'essaierais de ne pas risquer! –

+0

Merci @trashgod. Si elle dépend du compilateur, alors utilisez "in out" le seul moyen sûr de vous assurer que cela fonctionne (si vous n'êtes pas sûr que l'enregistrement transmis a une initialisation par défaut): 'procédure P2 (arg1: in out A) est ' ' begin' 'arg1.y: = 200;' 'fin P2;' –

+1

@TNguyen: J'ai développé plus haut. – trashgod