Ada95数组赋值更改指针或为每个元素分配?

时间:2013-10-04 08:00:43

标签: arrays variable-assignment atomic ada

在Ada95中,我们有两个相同类型的数组。如果我们像这样分配一个:

Array_A := Array_B;  

这究竟是做什么的?

它会迭代Array_B并依次将每个元素分配给Array_A吗?或者它只是将Array_A的地址更改为Array_B的地址?

询问的原因是我们需要知道这个赋值是否是原子操作。

4 个答案:

答案 0 :(得分:2)

Array_A的内容最终是Array_B元素的副本,即赋值遍历数组,分配每个元素。与C不同,Ada具有真正的数组对象。

因此,除非您以protected object之类的方式保护操作,否则赋值不是原子的。 (在受保护对象中包装数组赋值不会使其成为原子,它只是从应用程序其余部分的角度出现。)

答案 1 :(得分:2)

假设

type My_Array is array (1 .. 42) of Integer;
Array_A : My_Array;
Array_B : My_Array;

然后Array_AArray_B是不同的内存区域,在赋值后,Array_A的字节包含Array_B字节的副本。是通过迭代元素还是通过某些等价的memcpy(3)来完成传输取决于编译器编写器(pragma Atomic_Components会影响这个)。

如果另一方面你有

type My_Array is array (1 .. 42) of Integer;
type My_Array_P is access My_Array;
Array_A : My_Array_P;
Array_B : My_Array_P;

然后赋值将复制指针,并且可能是原子的(你可以添加pragma Atomic (My_Array_P);pragma Atomic (Array_A);来告诉编译器使访问值成为原子,或者如果可以的话就无法编译代码“T)。

答案 2 :(得分:1)

赋值语句复制数据。 Ada区分了包含数据的对象和仅对数据“引用”的对象;引用的对象具有access类型的类型(例如Simon的示例中的My_Array_P)。分配访问类型会导致引用指向同一个对象;但是,分配不是访问类型的对象总是会复制数据。

说数组赋值“在Array_B上迭代[s]并依次将每个元素[s]分配给Array_A”并不完全准确。如果数组元素类型是受控类型或具有受控子组件,那么Array_A := Array_B;必须最终确定Array_A的元素,之后它必须调整它们,但它按以下顺序发生:首先,{{1}的每个元素1}}最终确定(以任意顺序)。然后将数据从Array_A复制到Array_B(这可以一次完成一个元素,但在许多情况下,编译器可以将其优化为块复制)。然后调整Array_A的每个元素(再次,以任意顺序)。因此Array_A的语义不同于循环(我假设数组的上限和下限相同):

Array_A := Array_B

因为for I in Array_A'range loop Array_A (I) := Array_B (I); end loop; Finalize调用将以不同的顺序完成。通常这不会对程序产生任何影响,如果AdjustFinalize被正确写入(如果效果不同,程序设计可能有些奇怪)。但是,如果Adjust释放内存并Finalize分配新内存(例如在典型的Adjust实施中),则进行Unbounded_StringFinalize调用以不同的顺序可能会对内存碎片产生影响。

答案 3 :(得分:1)

问题的答案是,如果您希望编译器对它们进行原子分配,则应声明对象“Atomic”。

如果您的目标CPU没有适合对象类型的原子指令,它会抱怨。在这种情况下,您(至少)有一个替代解决方案:

  1. 将数组封装在受保护对象中,以确保对它们的操作是原子的。
  2. 使用访问类型和复制引用当然是一种选择,但它实际上是一种完全不同的操作,因此您应该仔细考虑这是否真的是您想要的。

    (如果有问题的数组很短,填充的布尔数组,你的编译器很可能能够使对象“Atomic”,否则我不会指望它。)