好的 . 我真的很讨厌这样简单的问题,但我已经完全阅读了三本不同的书籍,向我解释了访问类型和参数模式,我无法理解我做错了什么 .
我在Ada中创建了一个简单的shell,因为我对此很感兴趣,并且我认为到目前为止这是一个很好的学习经历 . 这是我的代码:
with Ada.Text_IO;
with Execute_System;
procedure Main is
package IO renames Ada.Text_IO;
Input : aliased String(1 .. 255) := (others=> ' ');
Last: Integer;
begin
IO.Put_Line("Welcome to ash! This is an extreme work in progress.");
Main_Loop:
loop
Input := (others=> ' ');
IO.Put("ash> ");
IO.Get_Line(Input, Last);
if Input(Input'First..Last) = "quit" then
exit Main_Loop;
else
Execute_System(Command => Input'Access);
end if;
end loop Main_Loop;
end Main;
Execute_System()所做的是传递给Spawn,而后者又由GNAT.OS_Lib库提供 . 编译时得到的错误是:
main.adb:6:04: warning: aliased object has explicit bounds
main.adb:6:04: warning: declare without bounds (and with explicit initialization)
main.adb:6:04: warning: for use with unconstrained access
main.adb:19:36: object subtype must statically match designated subtype
execute_system.adb:5:60: prefix of "Access" attribute must be aliased
gnatmake: "main.adb" compilation error
我不允许访问此字符串,因为它具有明确的边界 . 我已经在 new subtype Command_Access is access all String(1..255)
中看到了一个解决方案,但我还没有对子类型有所了解 .
有人可以解释我的问题吗?我已经使用没有访问参数模式的硬编码值测试了Execute_System过程,所以我不相信这是这个问题 .
2 回答
这是由于一个相当模糊的规则(RM 3.10.2(27ff)) . 但原因与实施困难有关 .
当变量或参数的类型
access String
没有边界时,必须有一种方法来在使用变量或参数时获取边界:如果
A
本质上只是字符串第一个字符的地址,那么就无法计算A'First
和A'Last
.解决此问题的一种常用方法是将字符串的边界存储为字符串第一个字符之前的两个整数 . 然后,当
S'Access
用作access String;
变量或参数的值时,代码知道字符串的第一个字符将以边界开头,因此它可以检索它们以获得A'First
和A'Last
的值 .这个解决方案的问题是它意味着每个别名
String
必须存储这些边界 . (我认为这只是aliased
对象的必要条件 . )如果你说的话然后编译器必须生成边界,因为它无法判断程序中的某个点(可能甚至在不同的包中),代码可能会尝试使用
S'Access
作为access String;
的值 . 即使S'Access
从未像这样使用过,也必须存储这些边界,因为编译器不会成为主要目标 .妥协是判断如果别名
String
S
没有作为类型的一部分的边界,那么将存储边界,并且您可以使用S'Access
作为access String
. 如果别名String
确实已将边界作为子类型的一部分,则不会存储边界,但您不能将S'Access
用作access String
(如果边界匹配,您仍可以将其用作access String(m..n)
) . 这意味着在这种情况下,存储边界:但在这种情况下,他们不是:
第一种形式是您可以在案例中使用的方法来解决问题 .
如果Ada有办法编写第二种类型的声明但仍然告诉编译器将其视为第一种 - 即 . 存储边界并允许
'Access
可用作access String
. 事实上,我相信那里有一个Ada问题(我不希望未来版本的Ada提供解决方案 .答案
尝试将
Input'Access
更改为Input'Unrestricted_Access
.属性Unrestricted_Access
属性
Unrestricted_Access
是GNAT的一个特性 . 它可以用于任何类型 .示例1
注释的代码行不起作用 .
示例2
正在行动demo .
外部资源
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gnat_rm/Unrestricted_005fAccess.html
评论
@ajb在评论中表示,bouandery
Str_Acc_5'First = Str_3'First
和Str_Acc_5'Last = Str_3'Last
可能是也可能不是 . 目前我还没有找到官方文件 . 另一方面boundary is matching on ideone.com .