XDR 標準規約で定義されているデータ型を説明します。
XDR 言語でどのようにデータ型を宣言するかを示します。
符号化方法を図示します。
XDR 言語で使用できる各データ型の宣言方法を示します。大小記号による括弧 (< と >) は可変長のデータシーケンスを示し、角括弧 [ と ])は固定長のデータシーケンスを示します。n、m、r は整数を表します。XDR 言語の詳細仕様については、「XDR 言語仕様」の節を参照してください。
いくつかのデータ型については、具体的なデータ記述例も示します。より詳しいデータ記述例については、「XDR データ記述 」を参照してください。
XDR の符号付き整数は、[-2147483648, 2147483647] の範囲の整数が符号化された 32 ビットデータです。整数は 2 の補数で表されます。最上位バイト (MSB) と最下位バイト (LSB) はそれぞれバイト 0 とバイト 3 です。
整数は次のように宣言します。
int identifier;
整数
XDR の符号なし整数は、[0, 4294967295] の範囲の正の整数が符号化された 32 ビットデータです。整数は符号なしの 2 進数で表されます。最上位バイト (MSB) と最下位バイト (LSB) はそれぞれバイト 0 とバイト 3 です。
符号なし整数は次のように宣言します。
unsigned int identifier;
符号なし整数
列挙型のデータ表現方法は符号付き整数と同じです。列挙型は、整数のサブセットを記述するのに便利です。
列挙型は次のように宣言します。
enum {name-identifier = constant , ... } identifier;
たとえば、列挙型を使用して赤、黄、青の 3 色を次のように表すことができます。
enum {RED = 2, YELLOW = 3, BLUE = 5} colors;
列挙型に、enum
宣言で指定されていない整数を代入しようとするとエラーになります。
「符号付き整数」を参照してください。
ブール型は、標準規約の明示型に対応するための型で、よく使用される重要なデータ型です。ブール型には、整数の 0 と 1 を使用します。
ブール型は次のように宣言します。
bool identifier;
これは、次の宣言と同じです。
enum {FALSE = 0, TRUE = 1} identifier;
「符号付き整数」を参照してください。
標準規約では 64 ビット (8 バイト) の整数として hyper
int
と unsigned
hyper
int
を定義しています。その表現方法は明らかに、上で説明した integer
と unsigned integer
を拡張したものです。hyper
整数は 2 の補数で表されます。最上位バイト (MSB) と最下位バイト (LSB) はそれぞれバイト 0 とバイト 7 です。
Hyper 整数は次のように宣言します。
hyper int identifier; unsigned hyper int identifier;
Hyper 整数
標準規約では、浮動小数点型 float
(32 ビット、すなわち 4 バイト) を定義しています。符号化方法は、正規化された単精度浮動小数点に関するIEEE 標準規約 [1] に従います。単精度浮動小数点は次の 3 つのフィールドで記述されます。
S: 符号を表す 1 ビットのフィールドです。0 が正、1 が負を表します。
E: 数値の指数部 (基数は 2) を表します。このフィールドは 8 ビットです。指数部の値を 127 だけバイアスした値が入っています。
F: 数値の仮数部 (基数は 2) を表します。このフィールドは 23 ビットです。
したがって、単精度浮動小数点型の値は次のように記述されます。
(-1)**S * 2**(E-Bias) * 1.F
単精度浮動小数点データは次のように宣言します。
float identifier;
倍精度浮動小数点データは次にように宣言します。
double identifier;
倍精度浮動小数点
整数の最上位バイトと最下位バイトがバイト 0 とバイト 3 であるのと同様に、倍精度浮動小数点型の値の最上位ビットと最下位ビットはビット 0 とビット 63 になります。S、E、F の各フィールドの開始ビット (最上位ビット) のオフセットはそれぞれ 0、1、12 になります。
これらのオフセットは論理的ビット位置を示すもので、物理的位置を示すものではありません (物理的位置は媒体によって異なります)。
符号付きゼロ、符号付き無限大 (オーバフロー)、正規化されない値 (アンダフロー) の符号化については、IEEE 標準規約 [1] を参照してください。IEEE 標準規約によると、NaN (not a number) は、システムごとに異なるため外部表現では使用できません。
標準規約では、4 倍精度浮動小数点型 quadruple
(128 ビット、すなわち 16 バイト) を定義しています。符号化方法は、正規化された 4 倍精度浮動小数点に関する IEEE 標準規約 [1] に従います。標準規約では、4 倍精度浮動小数点は次の 3 つのフィールドに符号化されます。
S: 符号を表す 1 ビットのフィールドです。0 が正、1 が負を表します。
E: 数値の指数部 (基数は 2) を表します。このフィールドは 15 ビットです。指数部の値を 16383 だけバイアスした値が入っています。
F: 数値の仮数部 (基数は 2) を表します。このフィールドは 111 ビットです。
したがって、4 倍精度浮動小数点型の値は次のように記述されます。
(-1)**S * 2**(E-Bias) * 1.F
quadruple identifier;
4 倍精度浮動小数点
整数の最上位バイトと最下位バイトがバイト 0 とバイト 3 であるのと同様に、4 倍精度浮動小数点型の値の最上位ビットと最下位ビットはビット0 とビット 127 になります。S、E、F の各フィールドの開始ビット (最上位ビット) のオフセットはそれぞれ 0、1、16 になります。これらのオフセットは論理的ビット位置を示すもので、物理的位置を示すものではありません。物理的位置は媒体によって異なります。
符号付きゼロ、符号付き無限大 (オーバフロー)、正規化されない値 (アンダフロー) の符号化については、IEEE 標準規約 [1] を参照してください。IEEE 標準規約によると、NaN (not a number) は、システムごとに異なるため外部表現では使用できません。
内容を解釈しない固定長データをマシン間で受け渡さなければならない場合があります。このデータを隠されたデータといいます。
隠されたデータは次のように宣言します。
opaque identifier[n];
ここで定数 n は、隠されたデータを入れるのに必要な (固定) バイト数です。n バイトの隠されたデータの後には、0 〜 3 個の余分なゼロバイト r が付加されて、隠されたオブジェクト全体のバイト数が 4 の倍数になるように調整されます。
n バイトの隠されたデータの後には、0 〜 3 個の余分なゼロバイト r が付加されて、隠されたオブジェクト全体のバイト数が 4 の倍数になるように調整されます。
固定長の隠されたデータ
標準規約では、可変長 (カウント付き) の隠されたデータも次のように定義されています。n バイトの任意のバイトシーケンス(バイト番号は 0 〜 n-1) がカウントされて下に示すように符号なし整数 n に符号化され、その後に n バイトのバイトシーケンスが続きます。
シーケンス内のバイト b は必ずバイト b+1 の直前に位置し、シーケンス内のバイト 0 はバイトシーケンスの長さ (カウント) の次に位置しています。n バイトのデータの後には、0〜 3 個の余分なゼロバイト r が付加されて、全体のバイト数が 4 の倍数になるように調整されます。
可変長の隠されたデータは次のように宣言します。
opaque identifier<m>;
または
opaque identifier<>;;
定数 m は、シーケンスに含まれるバイト数の上限を示します。2 番目の宣言のように m を指定しないと、最大バイト数は (2**32) - 1 となります。たとえば、ファイル伝送プロトコルで最大データ伝送サイズを 8192 バイトとするには、次のように宣言します。
opaque filedata<8192>;
可変長の隠されたデータ
指定した最大バイト数以上の長さを符号化するとエラーになります。
標準規約では、n バイトの ASCII 文字列 (バイト番号は 0〜 n-1) を次のように定義します。バイト数が符号なし整数 n に符号化されたものに、n バイトの文字列が続きます。文字列のバイト b は必ずバイト b+1 の直前に位置し、文字列のバイト 0 は文字列の長さの次に位置しています。n バイトのデータの後には、0 〜 3 個の余分なゼロバイト r が付加されて、全体のバイト数が 4 の倍数になるように調整されます。
カウント付きバイト文字列は次のように宣言します。
string object<m>;
または
string object<>;
定数 m は、文字列に含まれるバイト数の上限を示します。2 番目の宣言のように、m を指定しないと、最大バイト数は (2**32) - 1 となります。定数 m は、通常プロトコル仕様で決められています。たとえば、ファイル伝送プロトコルでファイル名を最大 255 バイトとするには、次のように宣言します。
string filename<255>;
文字列
指定した最大バイト数以上の長さを符号化するとエラーになります。
固定長配列の要素番号は 0 〜 n-1 で、個々の配列要素が 0 〜 n-1 の番号順に符号化されます。各配列要素のバイト数は 4 の倍数になっています。全要素が同一のデータ型であっても、要素のサイズが異なることがあります。たとえば、文字列の固定長配列の場合、要素のデータ型はすべて string
型ですが、個々の要素の長さは異なります。
各要素のデータ型がすべて同じである固定長配列は、次のように宣言します。
type-name identifier[n];
固定長配列
可変長配列をカウント付きで符号化することによって、固定長の要素と同じように符号化できます。要素カウント n (符号なし整数) に続けて、要素番号 0 〜 n-1 の順に各要素が符号化されます。
可変長配列は次のように宣言します。
type-name identifier<m>;
または
type-name identifier<>;
定数 m は、配列に含まれる要素数の上限を示します。m を指定しないと、最大要素数は (2**32) - 1 とみなされます。
可変長配列
仕様で決められた最大要素数より大きな長さを符号化するとエラーになります。
構造体の構成要素は、構造体の宣言で並べた順に符号化されます。各構成要素のサイズはそれぞれ異なる可能性がありますが、各々が 4 の倍数に調整されます。
構造体は次のように宣言します。
struct { component-declaration-A; component-declaration-B; ... } identifier;
構造体
識別型の共用体には、要素識別子に続いて、あらかじめ配置された一連のデータ型から要素識別子の値に応じて選択されたものが入ります。要素識別子のデータ型は、int
、unsigned int
、bool
などの列挙型、のいずれかです。共用体の構成要素の型をアームといい、符号化を暗黙に示す要素識別子に続けて記述されます。
識別型の共用体は次のように宣言します。
union switch (discriminant-declaration) { case discriminant-value-A: arm-declaration-A; case discriminant-value-B: arm-declaration-B; ... default: default-declaration; } identifier;
キーワード case の後には、要素識別子として指定できる値を書きます。デフォルトアームは省略できますが、その場合は要素識別子として定義されていない値を持つものを正しく符号化できません。各アームのサイズは、それぞれ 4 の倍数になります。
識別型の共用体は、要素識別子に続けて、それに対応するアームが符号化されます。
識別型の共用体
XDR の void
型は 0 バイトのデータです。void
は、入力データまたは出力データを持たない操作を記述するときに使用します。また、共用体で、アームによってデータを持つものと持たないときがある場合にも使用できます。
void の宣言は次のように簡単です。
void;
const
型は定数を表すシンボル名を定義するのに使用しますが、データを宣言するものではありません。シンボル定数は、通常の定数を使用できるところならどこでも使用できます。
次の例では、12 を表すシンボル定数 DOZEN を定義します。
const DOZEN = 12;
定数は次のように宣言します。
const name-identifier = n;
typedef
はデータを宣言するものではなく、新たな識別子でデータを宣言できるようにするためのものです。typedef
の構文を次に示します。
typedef declaration;
typedef
の宣言部分の変数名が、新たな型名になります。次の例では、既存の型 egg とシンボル定数 DOZEN を使用して、eggbox という新たな型を定義しています。
typedef egg eggbox[DOZEN];
新たな型名で宣言した変数は、typedef
で変数として見た場合の型と同じ型を持ちます。したがって、次の 2 つの宣言は同じ型の変数 fresheggs: を宣言しています。
eggbox fresheggs; egg fresheggs[DOZEN];
typedef
に struct
、enum
、union
の定義が含まれるときは、同じ型を定義するのに、別のより望ましい構文が使用できます。一般に、typedef
は次の形式で指定します。
typedef <<struct, union, or enum definition>> identifier;
この形式から typedef
を取り去り、最後の識別子を struct
、enum
、union
のキーワードの後に置くこともできます。bool
型を宣言する 2 つの方法を次に示します。
typedef enum {/* typedef を使用 */ FALSE = 0, TRUE = 1 } bool; enum bool {/* 望ましい方法 */ FALSE = 0, TRUE = 1 };
最初の構文では宣言の最後まで見ないと新しい型名がわからないので、後の構文の方が望ましい方法です。
オプションデータは共用体の一種ですが、次のような特殊な構文を持ち、非常によく使用されます。次のように宣言されます。
type-name *identifier;
これは次のように宣言した共用体と同じです。
union switch (bool opted) { case TRUE: type-name element; case FALSE: void; } identifier;
また、これは次のような可変長配列の宣言とも同じです。ブール型 opted は、配列の長さと解釈できるからです。
type-name identifier<1>;