Ada 访问静态地址的无约束类型
Ada Access to Unconstrained Type at Static Address
以下是非法的 Ada:
type Byte_Array is array (Natural range <>) of Interfaces.Unsigned_8;
type Byte_Array_Access is access all Byte_Array;
bytes : aliased Byte_Array(0 .. 9999);
for bytes'Address use To_Address(16#0040_0000#);
bytes_Access : Byte_Array_Access := bytes'Access;
编译器产生错误:
object subtype must statically match designated subtype
在最后一行。我看到的解决方法是像这样显式初始化数组:
bytes : aliased Byte_Array := (0 .. 9999 => 0);
但是,这对我不起作用,因为我在地址 16#0040_0000#
存储了无法覆盖的非易失性数据。我有哪些选择?
更多信息:
我想补充一点,您可以通过以下方式避免显式初始化数组:
bytes : aliased Byte_Array := (0 .. 9999 => <>);
然而,这仍然无法编译,产生不同的错误:
aliased object "bytes" with unconstrained array nominal subtype
can overlay only aliased object with compatible subtype
线上 for bytes'Address use To_Address(16#0040_0000#);
.
制作自己的 'accessor' 有帮助吗?像
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces;
with System;
with System.Address_Image;
procedure Byte_Arrays is
type Byte_Array is array (Natural range <>) of Interfaces.Unsigned_8;
package Access_Byte_Array is
type Byte_Array_Access is private;
function Form_Access (Of_Array : Byte_Array) return Byte_Array_Access;
function Address (Of_Array : Byte_Array_Access) return System.Address;
function Length (Of_Array : Byte_Array_Access) return Integer;
private
type Byte_Array_Access is record
The_Array : System.Address;
First : Natural;
Last : Integer; -- could have zero length
end record;
function Address (Of_Array : Byte_Array_Access) return System.Address
is (Of_Array.The_Array);
function Length (Of_Array : Byte_Array_Access) return Integer is
(if Of_Array.Last < Of_Array.First
then 0
else Of_Array.Last - Of_Array.First + 1);
end Access_Byte_Array;
package body Access_Byte_Array is
function Form_Access (Of_Array : Byte_Array) return Byte_Array_Access
is
begin
return (The_Array => Of_Array'Address,
First => Of_Array'First,
Last => Of_Array'Last);
end Form_Access;
end Access_Byte_Array;
use Access_Byte_Array;
Bytes : aliased Byte_Array(0 .. -9999);
for Bytes'Address use System'To_Address(16#0040_0000#);
Bytes_Access : constant Byte_Array_Access := Form_Access (Bytes);
begin
Put_Line (Length (Bytes_Access)'Image);
Put_Line (System.Address_Image (Address (Bytes_Access)));
end Byte_Arrays;
有输出
$ ./byte_arrays
10000
0000000000400000
[稍后] 对于 macOS 上的 FSF GNAT 10.1.0,这些更改有效:
type Standard_Access is access all Byte_Array;
...
function Standard_Accessor
(Of_Array : aliased Byte_Array_Access) return Standard_Access;
...
type Bounds is record
Lower : Integer;
Upper : Integer;
end record with Pack;
type Byte_Array_Access is record
The_Array : System.Address;
The_Bounds : Bounds;
end record;
...
function Standard_Accessor
(Of_Array : aliased Byte_Array_Access) return Standard_Access
is
type Raw_Accessor is record
Contents : System.Address;
Bounds_P : System.Address;
end record with Pack;
function Convert
is new Ada.Unchecked_Conversion (Raw_Accessor, Standard_Access);
Raw_Result : constant Raw_Accessor
:= (Contents => Of_Array.The_Array,
Bounds_P => Of_Array.The_Bounds'Address);
begin
return Convert (Raw_Result);
end Standard_Accessor;
Standard_Accessor
的参数必须使用别名,以便通过引用而不是在堆栈上传递。当然,你必须小心不要在 Standard_Access
存在时删除它,所以也许最好总是在包级别声明。
以下是非法的 Ada:
type Byte_Array is array (Natural range <>) of Interfaces.Unsigned_8;
type Byte_Array_Access is access all Byte_Array;
bytes : aliased Byte_Array(0 .. 9999);
for bytes'Address use To_Address(16#0040_0000#);
bytes_Access : Byte_Array_Access := bytes'Access;
编译器产生错误:
object subtype must statically match designated subtype
在最后一行。我看到的解决方法是像这样显式初始化数组:
bytes : aliased Byte_Array := (0 .. 9999 => 0);
但是,这对我不起作用,因为我在地址 16#0040_0000#
存储了无法覆盖的非易失性数据。我有哪些选择?
更多信息:
我想补充一点,您可以通过以下方式避免显式初始化数组:
bytes : aliased Byte_Array := (0 .. 9999 => <>);
然而,这仍然无法编译,产生不同的错误:
aliased object "bytes" with unconstrained array nominal subtype
can overlay only aliased object with compatible subtype
线上 for bytes'Address use To_Address(16#0040_0000#);
.
制作自己的 'accessor' 有帮助吗?像
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces;
with System;
with System.Address_Image;
procedure Byte_Arrays is
type Byte_Array is array (Natural range <>) of Interfaces.Unsigned_8;
package Access_Byte_Array is
type Byte_Array_Access is private;
function Form_Access (Of_Array : Byte_Array) return Byte_Array_Access;
function Address (Of_Array : Byte_Array_Access) return System.Address;
function Length (Of_Array : Byte_Array_Access) return Integer;
private
type Byte_Array_Access is record
The_Array : System.Address;
First : Natural;
Last : Integer; -- could have zero length
end record;
function Address (Of_Array : Byte_Array_Access) return System.Address
is (Of_Array.The_Array);
function Length (Of_Array : Byte_Array_Access) return Integer is
(if Of_Array.Last < Of_Array.First
then 0
else Of_Array.Last - Of_Array.First + 1);
end Access_Byte_Array;
package body Access_Byte_Array is
function Form_Access (Of_Array : Byte_Array) return Byte_Array_Access
is
begin
return (The_Array => Of_Array'Address,
First => Of_Array'First,
Last => Of_Array'Last);
end Form_Access;
end Access_Byte_Array;
use Access_Byte_Array;
Bytes : aliased Byte_Array(0 .. -9999);
for Bytes'Address use System'To_Address(16#0040_0000#);
Bytes_Access : constant Byte_Array_Access := Form_Access (Bytes);
begin
Put_Line (Length (Bytes_Access)'Image);
Put_Line (System.Address_Image (Address (Bytes_Access)));
end Byte_Arrays;
有输出
$ ./byte_arrays
10000
0000000000400000
[稍后] 对于 macOS 上的 FSF GNAT 10.1.0,这些更改有效:
type Standard_Access is access all Byte_Array;
...
function Standard_Accessor
(Of_Array : aliased Byte_Array_Access) return Standard_Access;
...
type Bounds is record
Lower : Integer;
Upper : Integer;
end record with Pack;
type Byte_Array_Access is record
The_Array : System.Address;
The_Bounds : Bounds;
end record;
...
function Standard_Accessor
(Of_Array : aliased Byte_Array_Access) return Standard_Access
is
type Raw_Accessor is record
Contents : System.Address;
Bounds_P : System.Address;
end record with Pack;
function Convert
is new Ada.Unchecked_Conversion (Raw_Accessor, Standard_Access);
Raw_Result : constant Raw_Accessor
:= (Contents => Of_Array.The_Array,
Bounds_P => Of_Array.The_Bounds'Address);
begin
return Convert (Raw_Result);
end Standard_Accessor;
Standard_Accessor
的参数必须使用别名,以便通过引用而不是在堆栈上传递。当然,你必须小心不要在 Standard_Access
存在时删除它,所以也许最好总是在包级别声明。