1

我试图'Last在 Ada 中将属性与 2D 数组一起使用,但我似乎找不到这样做的正确语法。

我知道如果我有一个一维数组/向量,我可以使用 A'last 或 A'last(n) 其中 n 是第 n 维。但是,如果我执行以下操作

type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;

function temp(tempIn : in Integer;
              Table  : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);

begin
    for i in 0..tempTable'last(1) loop
        for j in 0..tempTable'last(2) loop
            tempTable(i, j) := Table(i,j);
        end loop;
    end loop;
end temp;

我收到以下编译时错误:

Storage_Error 堆栈溢出(或错误的内存访问)

那么我做错了什么?

我在 Linux 上使用 GNAT Pro 6.4.1。

4

3 回答 3

3

如果您对该代码有编译时间 ,我会感到非常惊讶。Storage_Error

我已经获取了您的代码副本并对其进行了如下修改;它使用 GNAT (gcc-4.4) 编译没有错误:

procedure Array_2D is
    type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;

    function temp(tempIn : in Integer;
                  Table  : in UnconstrainedArray_2D) return Integer is
    tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);

    begin
        for i in 0..tempTable'last(1) loop
            for j in 0..tempTable'last(2) loop
                tempTable(i, j) := Table(i,j);
            end loop;
        end loop;
        return 42; -- added this
    end temp;
begin
    null;
end Array_2D;

(请注意,我必须在 中添加缺少的return语句temp。)

您的属性语法'Last(不是“命令”)是正确的,但由于 Ada 数组可以有任意的下限和上限,因此最好使用该'Range属性:

    for i in tempTable'Range(1) loop
        for j in tempTable'Range(2) loop
            tempTable(i, j) := Table(i,j);
        end loop;
    end loop;

至于Storage_Error异常,如果您调用temp具有非常大的tempIn. 请记住,它必须分配足够的空间来容纳tempIn**2 Integer对象。大概您还创建了另一个UnconstrainedArray_2D要作为Table参数传入的对象。

可以想象,编译器本身可能会因Storage_Error异常而死,但我在您的代码中看不到任何可能导致这种情况的东西。

向我们展示一个完整的(但很小的)程序来演示您遇到的问题,以及确切的(复制和粘贴的)错误消息。请清楚地区分编译时错误和运行时错误。

于 2012-04-04T21:44:26.783 回答
2

tempTable可能有一个范围0..tempIn,但你不知道你Table有什么范围..它们也可能有不同的长度。

您必须检查长度是否相同,然后使用相对索引,如下所示:

function temp(tempIn : in Integer;
              Table  : in UnconstrainedArray_2D) return Integer is
    tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);

begin
    if tempTable'Length (1) /= Table'Length (1) or else
      tempTable'Length (2) /= Table'Length (2)
    then
       raise Constraint_Error; -- or something else
    end if;
    for i in 0 .. tempTable'Length (1) - 1 loop
        for j in 0 .. tempTable'Length (2) - 1 loop
            tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
              Table(Table'First (1) + i, Table'First (2) + j);
        end loop;
    end loop;
end temp;

这样可以确保两个表的长度相同并且所有索引都有效。

如果tempTable允许小于Table,只需将长度检查调整为>。指数仍然有效。

于 2012-04-05T06:33:44.550 回答
0

我没有看到tempIn集的实际值。如果tempIn进入函数 temp 的值没有正确初始化或显式设置,则tempIn中的值可以是任何值,也可能不是您想要的值。


我在考虑一个默认值。(当我感觉不舒服时可能不应该发帖:-)

于 2012-04-06T14:17:26.520 回答