Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 如何在Ada中将对受约束字符串的访问权传递给子程序_Pointers_Ada - Fatal编程技术网

Pointers 如何在Ada中将对受约束字符串的访问权传递给子程序

Pointers 如何在Ada中将对受约束字符串的访问权传递给子程序,pointers,ada,Pointers,Ada,好的。我真的不喜欢问这样的简单问题,但我已经读了三本书,向我解释了访问类型和参数模式,我无法理解我做错了什么 我正在用Ada创建一个简单的shell,因为我对此很感兴趣,我认为到目前为止这是一次很好的学习经历。这是我的密码: with Ada.Text_IO; with Execute_System; procedure Main is package IO renames Ada.Text_IO; Input : aliased String(1 .. 255) := (othe

好的。我真的不喜欢问这样的简单问题,但我已经读了三本书,向我解释了访问类型和参数模式,我无法理解我做错了什么

我正在用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
我不明白为什么我不能访问这个字符串,仅仅因为它有显式的边界。我在
新建子类型命令\u Access is Access all String(1..255)
中看到了一个解决方案,但我不明白为什么这是一个解决方案(请原谅语法错误,我对子类型还是比较陌生)


有人能解释一下我的问题吗?我已经用硬编码的值测试了Execute_系统过程,但没有访问参数模式,所以我不认为是这个问题。

这是由于一个相当模糊的规则(RM 3.10.2(27ff))。但原因与实施困难有关

当变量或参数的类型
访问字符串
没有边界时,在使用变量或参数时,必须有一种获取边界的方法:

procedure Some_Procedure (A : access String) is 
     First, Last : Integer;
begin
     First := A'First;
     Last := A'Last;
     ...
end Some_Procedure;
如果
A
实际上只是字符串的第一个字符的地址,那么就无法计算
A'first
A'Last

解决此问题的一种常用方法是将字符串的边界存储为字符串第一个字符前面的两个整数。然后,当
S'Access
用作
访问字符串的值时变量或参数时,代码知道字符串的第一个字符前面将有边界,因此可以检索它们以获得
A'first
A'Last
的值

这种解决方案的明显问题是,它意味着每个别名
字符串
都必须存储这些边界。(我认为这只对有别名的对象才有必要。)

S : aliased String(1..100);
然后,编译器必须生成边界,因为它无法判断在程序中的某个点(甚至在不同的包中),代码是否会尝试使用
S'Access
作为
访问字符串的值。即使
S'Access
从未被这样使用过,也必须存储这些边界,因为编译器无法预测将来代码可能会这样做。这将导致空间浪费。这不是一件好事,因为嵌入式系统是Ada的主要目标之一

折衷办法是,如果别名为
的字符串
S
没有作为类型一部分的边界,那么边界将被存储,并且您可以使用
S'Access
来访问
字符串
。如果别名为
的字符串
确实具有作为子类型一部分的边界,则不会存储边界,但您不能将
S'Access
用作
Access字符串
(如果边界匹配,您仍然可以将其用作
Access字符串(m..n)
)。这意味着在这种情况下,将存储边界:

Input : aliased String := (1 .. 255 => ' ');
但在这种情况下,它们不是:

Input : aliased String(1 .. 255) := (others=> ' ');
第一种形式是你可以在你的案例中使用什么来回避问题

如果Ada能够编写第二种类型的声明,但仍然告诉编译器将其视为第一种类型,即存储边界并允许
'Access
可用作
访问字符串,那就太好了。事实上,我相信有一个Ada问题(我不想去查)提出了一个可能的语法。我记得,有人讨论过几种可能的语法,它们都很难看,所以这件事就不提了,但Ada的未来版本可能会提供解决方案。

答案 尝试将
Input'Access
更改为
Input'Unrestricted\u Access

属性无限制访问 属性
无限制访问
是GNAT的一个特性。它可以用于任何类型

例1 注释的代码行不起作用

type String\u Access为Access all String;
函数Str_10返回字符串为
S:字符串(1..10);
开始
返回S;
结束;
Str_1:别名字符串:=“0123456789”;
Str_2:别名字符串:=Str_10;
Str_3:别名字符串(1..10):=(其他=>'0');
Str_Acc_1:String_Access:=Str_1'Access;
Str_Acc_2:String_Access:=Str_2'Access;
--Str_Acc_3:String_Access:=Str_3'Access;
--Str_Acc_4:字符串访问:=Str_3'未检查的访问;
Str_Acc_5:String_Access:=Str_3'Unrestricted_Access;
例2 在行动中工作

带有Ada.Text\u IO;使用Ada.Text\u IO;
使用Ada.Integer\u Text\u IO;使用Ada.Integer\u Text\u IO;
程序程序是
类型String\u Access是Access all String;
Str_2:别名字符串(50..60);
Str_3:别名字符串(1..10):=(其他=>'0');
Str_Acc_5:String_Access:=Str_3'Unrestricted_Access;
开始
放置(Str_Acc_5'First);
新线;
放置(Str_Acc_5'Last);
Str_Acc_5:=Str_2'无限制访问;
新线;
放置(Str_Acc_5'First);
新线;
放置(Str_Acc_5'Last);
结束程序;
外部资源

Unrestricted_Access属性与Access类似,只是省略了所有可访问性和别名视图检查。这是一个用户注意属性。它类似于Address,对于Address,它是一个理想的替换,其中所需的值是访问类型。换句话说,其效果与首先应用Address属性,然后对所需的访问类型执行未经检查的转换相同。在GNAT中,但不一定在其他实现中,内部级子程序使用静态链意味着应用于子程序的不受限制的_访问产生一个值,只要子程序在范围内(正常Ada 95),就可以调用该值