最小単位の型とアドレス値の変換

昔書いた駄文が出てきたので貼っときます。http://d.hatena.ne.jp/ytqwerty/20050805#p1の続きらしい。Adaのライブラリは最悪だシリーズ2。
メモリやら何がしかについて直接アクセスができたりする言語では、当然ながらその最小単位として使われる型があります。
普通ならそれはバイトを意味する型です。
C言語はなんでもcharで済ませてしまっていますが、Dならubyte、PascalならByte、Javaですらbyteと、とにかくバイト(8ビット)です。UTF-9が格納できないバイトという単位が、あらゆる言語で、最小の整数値型、メモリ、文字、外部記憶、全ての単位となっています。sizeofやSizeOfの単位もバイトです。だからこそ、同じ型として、何の変換も無くあちらからこちらへデータを代入できたりポインタを受け渡したりできています。
…もうおわかりですね。
Adaはこれらの最小単位の型がそれぞれ違うのです。
メモリはSystem.Storage_Element、文字はCharacter(8ビット固定)、外部記憶はAda.Streams.Stream_Elementという具合です。整数値型の最小はShort_Short_Integerというのもありますが部分範囲型のある言語ですので更に小さくもできますし意識する必要も無いです。
それで、スカラー値同士は普通に型変換できるのですが、困るのが配列の受け渡しです。
Adaは、C言語のようにポインタが配列のように振舞う言語でもなければ、D言語のように先頭アドレスと要素数を簡単に組にして扱えるようにもなっていません。しかも無制約配列のメモリ上への確保のされ方はかなり複雑で文脈次第のところがあったりします。
何が言いたいかといいますと、UTF-9が普通に使えてしまうような12ビットCPU上ならともかく、何でもかんでもバイトの世界では、Stream_Elementの配列をキャストしてStringを受け取る関数に渡したいのです。日頃何の疑いも無く普通にやっているように。ところが、それがAdaでは物凄く難しいのです。
配列Sがあったとします。先頭アドレスはS(S'First)'Addressで取れます。長さはS'Lengthで取れます。先頭アドレスと長さから要素サイズが同じで別の型の無制約配列へのアクセス型の値(範囲データ付きポインタ)を作る。Dではわずか(cast(char*)&S[0])[0..S.length]だけで済む型変換です。
標準ライブラリには、アドレス値と特定の型のアクセス値を相互に変換するSystem.Address_To_Access_Conversionsなる使えないパッケージもありますが、これは使えません。今回の目的にも使えないのは勿論のこと、どれぐらい使えないかというと、GNAT付属の標準ライブラリ実装でアドレスの型を変換する必要があるところではほぼAda.Unchecked_Conversionが使われてしまっているぐらいです。そもそも関数名がTo_PointerだったりするあたりInterfaces.Cの中から迷い出てきたのではないかと思うぐらいです。AARMには、アドレスとアクセス値の内部表現が同じとは限らないためUnchecked_Conversionより望ましいみたいなことが書かれていますが、一方でアクセス値とC言語のポインタの内部表現が同じであることは保証されていたりします。アクセス値に追加の情報が付くのは指す先がIndefinite型の場合でありC言語にはこの手の型が存在しません。一方でSystem.Address_To_Access_ConversionsもIndefinite型を扱えません。
結論としてSystem.Address_To_Access_Conversionsはフラットメモリモデル環境では役に立ちません。セグメントとオフセットが分かれていたりすると意味があるんでしょう、たぶん。