Ada无界字符串无法使用'First/'Last?是GNAT Bug还是误用?
关于Ada无界字符串'First/'Last属性的问题
问题场景
尝试获取无界字符串的首个或最后索引时,编写了如下Ada程序:
with Ada.Strings; use Ada.Strings; -- 用于`Backward` with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; procedure Foo is package U_Str renames Ada.Strings.Unbounded; S : U_Str.Unbounded_String := U_Str.To_Unbounded_String ("example unbounded string"); I : Natural := U_Str.Index (Source => S, Pattern => "s", Going => Backward, From => S'Last); begin Put_Line (I'Image); end Foo;
使用GNAT编译时出现报错:
$ gnatmake foo.adb x86_64-linux-gnu-gcc-10 -c foo.adb foo.adb:12:41: prefix for "Last" attribute may not be private type gnatmake: "foo.adb" compilation error
而使用常规String的相同逻辑程序可正常编译运行:
with Ada.Strings; use Ada.Strings; -- 用于`Backward` with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; procedure Foo is package F_Str renames Ada.Strings.Fixed; S : String := "example fixed string"; I : Natural := F_Str.Index (Source => S, Pattern => "s", Going => Backward, From => S'Last); begin Put_Line (I'Image); end Foo;
编译运行结果:
$ gnatmake foo.adb x86_64-linux-gnu-gcc-10 -c foo.adb x86_64-linux-gnu-gnatbind-10 -x foo.ali x86_64-linux-gnu-gnatlink-10 foo.ali $ ./foo 15
疑问
无界字符串是否没有'First和'Last属性?Ada参考手册仅说明数组类型或约束数组子类型可使用这些属性,未提及私有类型。这是GNAT的Bug还是遗漏了某些要点?
问题解答
无界字符串确实不具备
'First和'Last属性Ada.Strings.Unbounded.Unbounded_String是私有类型,而非数组类型。Ada语言规范明确'First、'Last这类属性仅适用于数组类型或约束数组子类型,私有类型默认不提供这些属性,因此GNAT的报错完全符合规范,并非Bug。获取无界字符串索引边界的正确方式
要操作无界字符串的边界,需使用Ada.Strings.Unbounded包提供的专用接口:- 获取字符串长度:
U_Str.Length(S),返回字符总数 - 等效于
S'Last的位置:直接使用U_Str.Length(S),因为Ada字符串索引默认从1开始,最后一个字符的索引等于长度 - 等效于
S'First的位置:固定为1,无需额外函数
- 获取字符串长度:
修改后的无界字符串程序可正常运行:
with Ada.Strings; use Ada.Strings; -- 用于`Backward` with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; procedure Foo is package U_Str renames Ada.Strings.Unbounded; S : U_Str.Unbounded_String := U_Str.To_Unbounded_String ("example unbounded string"); I : Natural := U_Str.Index (Source => S, Pattern => "s", Going => Backward, From => U_Str.Length(S)); begin Put_Line (I'Image); end Foo;
- 固定字符串与无界字符串的核心区别
固定String是原生数组类型,天然继承数组的所有属性;无界字符串是封装后的私有类型,内部可能基于数组实现,但对外隐藏了底层细节,必须通过包提供的函数进行操作。
内容的提问来源于stack exchange,提问作者zorleone
相关产品推荐
相关产品推荐

