Oracle® Solaris Studio 12.4: C ユーザーガイド

印刷ビューの終了

更新: 2014 年 12 月
 
 

ISO C データ表現

この付録では、ISO C の記憶装置におけるデータ表現と、関数に引数を渡す仕組みについて説明します。C 言語以外の言語でモジュールを記述したり使用したいプログラマが、それらのモジュールに C 言語コードとのインタフェースを持たせるための手引きとして役立つかもしれません。

G.1 記憶領域の割り当て

データ型とその表現方法について次の表にまとめます。サイズはバイト単位です。


注 - スタックへの記憶装置の割り当て (内部リンクつまり自動リンクを伴う識別子を使用) は、2G バイト以下に制限すべきです。
表 G-1  データ型の記憶装置の割り当て
C の型
LP64 (-m64) サイズ
LP64 境界整列
ILP32 (-m32) サイズ
ILP 32 境界整列
整数
_Bool
char
signed char
unsigned char
1
1
1
1
short
signed short
unsigned short
2
2
2
2
int
signed int
unsigned int
enum
4
4
4
4
long
signed long
unsigned long
8
8
4
4
long long
signed long long
unsigned long long
8
8
8
4 (x86) / 8 (SPARC)
ポインタ
任意の型 *
任意の型 (*) ()
8
8
4
4
浮動小数点
float
double
long double
4
8
16
4
8
16
4
8
12 (x86) / 16 (SPARC)
4
4 (x86) / 8 (SPARC)
4 (x86) / 8 (SPARC)
複素数
float _Complex
double _Complex
long double _Complex
8
16
32
4
8
16
8
16
24 (x86) / 32 (SPARC)
4
4 (x86) / 8 (SPARC)
4 (x86) / 16 (SPARC)
虚数
float _Imaginary
double _Imaginary
long double _Imaginary
4
8
16
4
8
16
4
8
12 (x86) / 16 (SPARC)
4
4 (x86) / 8 (SPARC)
4 (x86) / 16 (SPARC)

G.2 データ表現

与えられたデータ要素のビット番号の割り当ては、使用しているアーキテクチャーによって異なります。SPARCstation マシンではビット 0 を最下位有効ビット、バイト 0 を最上位有効バイトとしてそれぞれ使用します。次の表に表現方法を示します。

G.2.1 整数表現

ISO C で使用されている整数型は shortintlong、および long long です。

表 G-2  short の表現
ビット数
内容
8- 15
バイト 0 (SPARC)
バイト 1 (x86)
0- 7
バイト 1 (SPARC)
バイト 0 (x86)
表 G-3  int の表現
ビット数
内容
24- 31
バイト 0 (SPARC)
バイト 3 (x86)
16- 23
バイト 1 (SPARC)
バイト 2 (x86)
8- 15
バイト 2 (SPARC)
バイト 1 (x86)
0- 7
バイト 3 (SPARC)
バイト 0 (x86)
表 G-4  -m32 でコンパイルされる long の表現
ビット数
内容
24- 31
バイト 0 (SPARC)
バイト 3 (x86)
16- 23
バイト 1 (SPARC)
バイト 2 (x86)
8- 15
バイト 2 (SPARC)
バイト 1 (x86)
0- 7
バイト 3 (SPARC)
バイト 0 (x86)
表 G-5  long (-m64) および long long (-m32 と -m64 の両方) の表現
ビット数
内容
56- 63
バイト 0 (SPARC)
バイト 7 (x86)
48- 55
バイト 1 (SPARC)
バイト 6 (x86)
40- 47
バイト 2 (SPARC)
バイト 5 (x86)
32- 39
バイト 3 (SPARC)
バイト 4 (x86)
24- 31
バイト 4 (SPARC)
バイト 3 (x86)
16- 23
バイト 5 (SPARC)
バイト 2 (x86)
8- 15
バイト 6 (SPARC)
バイト 1 (x86)
0- 7
バイト 7 (SPARC)
バイト 0 (x86)

G.2.2 浮動小数点表現

floatdoublelong double のデータ要素は、ISO IEEE 754-1985 規格に従って表現されます。表現は次のとおりです。

(-1)s *2(e - bias) *[j.f]

ここでは:

  • s は符号

  • e はバイアス付きの指数

  • j = 先行ビット。e の値によって決まる。long double (x86) では、先行ビットは明示的。そのほかは暗黙的。

  • f = 仮数部

  • u は、ビットが 0 でも 1 でも良いことを意味します (このセクションの表で使用)。

IEEE Single および Double の場合、j は常に暗黙的です。バイアス付きの指数が 0 の場合、f が 0 でない限り、j は 0 で、結果として生成される数値は非正規数です。バイアス付きの指数が 0 より大きい場合、数値が有限である限り j は 1 です。

Intel 80 ビット拡張の場合、j は常に明示的です。

各ビットの位置は次の表のとおりです。

表 G-6  float の表現
ビット数
名前
31
符号
23- 30
バイアス付きの指数
0- 22
仮数部
表 G-7  double の表現
ビット数
名前
63
符号
52- 62
バイアス付きの指数
0- 51
仮数部
表 G-8  longdouble の表現 (SPARC)
ビット数
名前
127
符号
112- 126
バイアス付きの指数
0- 111
仮数部
表 G-9  longdouble の表現 (x86)
ビット数
名前
80- 95
使用されない
79
符号
64- 78
バイアス付きの指数
63
先行ビット
0- 62
仮数部

詳細については、『数値計算ガイド』を参照してください。

G.2.3 極値

正規化された floatdouble の数は「隠された」ビットまたは暗黙のビットを持つと言われます。それにより、精度を 1 ビット分高めることができます。long double の場合は、先行ビットは暗黙的 (SPARC) または明示的 (x86) のいずれかになります。このビットは正規数に対しては 1、非正規数に対しては 0 になります。

表 G-10  float の表現
正規数 (0<e<255):
(-1)s2 (e-127)1.f
非正規数
(e=0, f!=0):
(-1)s2 (-126)0. f
ゼロ (e=0, f=0):
(-1)s0.0
シグナルを発生する NaN
s=u, e=255(最大値); f=.0uuu~uu (少なくとも 1 ビットは 0 以外)
シグナルを発生しない NaN
s=u, e=255(最大値); f=.1uuu~uu
無限大
s=u, e=255(最大値); f=.0000~00 (すべてが 0)
表 G-11  double の表現
正規数 (0<e<2047):
(-1)s2 (e-1023)1.f
非正規数 (e=0, f!=0):
(-1)s2 (-1022)0. f
ゼロ (e=0, f=0):
(-1)s0.0
シグナルを発生する NaN
s=u, e=2047(最大値); f=.0uuu~uu (少なくとも 1 ビットは 0 以外)
シグナルを発生しない NaN
s=u, e=2047(最大値); f=.1uuu~uu
無限大
s=u, e=2047(最大値); f=.0000~00 (すべてが 0)
表 G-12  longdouble の表現
正規数 (0<e<32767):
(-1)s2 (e- 16383)1.f
非正規数 (e=0, f!=0):
(-1)s2 (-16382)0.f
ゼロ (e=0, f=0):
(-1)s0.0
シグナルを発生する NaN
s=u, e=32767(符号); f=.0uuu~uu (少なくとも 1 ビットは 0 以外)
シグナルを発生しない NaN
s=u, e=32767(最大値); f=.1uuu~uu
無限大
s=u, e=32767(最大値); f=.0000~00 (すべてが 0)

G.2.4 重要な数の 16 進数表現

よく使用される数値の 16 進数表現を次の表にまとめます。

表 G-13  重要な数の 16 進数表現 (SPARC)
float
double
long double
+0
-0
00000000
80000000
0000000000000000
8000000000000000
00000000000000000000000000000000
80000000000000000000000000000000
+1.0
-1.0
3F800000
BF800000
3FF0000000000000
BFF0000000000000
3FFF00000000000000000000000000000
BFFF00000000000000000000000000000
+2.0
+3.0
40000000
40400000
4000000000000000
4008000000000000
40000000000000000000000000000000
40080000000000000000000000000000
プラス無限大
マイナス無限
7F800000
FF800000
7FF0000000000000
FFF0000000000000
7FFF00000000000000000000000000000
FFFF00000000000000000000000000000
NaN
7FBFFFFF
7FF7FFFFFFFFFFFF
7FFF7FFFFFFFFFFFFFFFFFFFFFFFFFFF
表 G-14  重要な数の 16 進数表現 (x86)
float
double
long double
+0
-0
00000000
80000000
0000000000000000
0000000080000000
00000000000000000000
80000000000000000000
+1.0
-1.0
3F800000
BF800000
000000003FF00000
00000000BFF00000
3FFF8000000000000000
BFFF8000000000000000
+2.0
+3.0
40000000
40400000
0000000040000000
0000000040080000
40008000000000000000
4000C000000000000000
プラス無限大
マイナス無限
7F800000
FF800000
000000007FF00000
00000000FFF00000
7FFF8000000000000000
FFFF8000000000000000
NaN
7FBFFFFF
FFFFFFFF7FF7FFFF
7FFFBFFFFFFFFFFFFFFF

詳細については、『数値計算ガイド』を参照してください。

G.2.5 ポインタ表現

C 言語におけるポインタは 4 バイトを使用します。C のポインタは、64 ビット SPARC v9 アーキテクチャーでは 8 バイトを占有します。NULL 値のポインタはゼロと等価です。

G.2.6 配列の格納

配列は、それぞれの要素が決められた記憶順序で格納されます。各要素は実際には記憶要素の一次元の列に格納されます。

C の配列は行メジャー順で格納されます。多次元配列の最後の添字はもっとも速く変化します。

文字列データ型は char 要素の配列です。連結後、文字列リテラルまたはワイド文字列リテラルに指定できる最大の文字数は、4,294,967,295 個です。

スタックに割り当てられた記憶領域のサイズ制限については、記憶領域の割り当てを参照してください。

表 G-15  配列の型と最大の大きさ
-m32 の要素の最大数
-m64 の要素の最大数
char
4,294,967,295
2,305,843,009,213,693,951
short
2,147,483,647
1,152,921,504,606,846,975
int
1,073,741,823
576,460,752,303,423,487
long
1,073,741,823
288,230,376,151,711,743
float
1,073,741,823
576,460,752,303,423,487
double
536,870,911
288,230,376,151,711,743
long double
268,435,451
144,115,188,075,855,871
long long
536,870,911
288,230,376,151,711,743

静的および大域配列にはさらに多くの要素を格納することができます。

G.2.7 極値の算術演算

このセクションでは、浮動小数点の極値と通常値を組み合わせたものに基本算術演算を適用して得られる結果について説明します。トラップやその他の例外は起こらないものとします。

次の表で、略語を説明します。

表 G-16  略語の使用法
略語
意味
Num
非正規のまたは正規化された数字
Inf
無限大 (正または負)
NaN
数字ではない
Uno
順序不定

次の表は、異なるタイプのオペランドを組み合わせて行なった算術演算から得られた値のタイプを示しています。

表 G-17  加算と減算の結果
右側のオペランド: 0
右側のオペランド: Num
右側のオペランド: Inf
右側のオペランド: NaN
左側のオペランド: 0
0
Num
Inf
NaN
左側のオペランド: Num
Num
を参照してください。

Num + Num は、結果が大きすぎる (オーバーフロー) 場合は Num ではなく Inf になることがあります。無限量が逆の sign の場合は、Inf + Inf = NaN になります。

Inf
NaN
左側のオペランド: Inf
Inf
Inf
を参照
NaN
左側のオペランド: NaN
NaN
NaN
NaN
NaN
表 G-18  乗算結果
右側のオペランド: 0
右側のオペランド: Num
右側のオペランド: Inf
右側のオペランド: NaN
左側のオペランド: 0
0
0
NaN
NaN
左側のオペランド: Num
0
Num
Inf
NaN
左側のオペランド: Inf
NaN
Inf
Inf
NaN
左側のオペランド: NaN
NaN
NaN
NaN
NaN
表 G-19  除算結果
右側のオペランド: 0
右側のオペランド: Num
右側のオペランド: Inf
右側のオペランド: NaN
左側のオペランド: 0
NaN
0
0
NaN
左側のオペランド: Num
Inf
Num
0
NaN
左側のオペランド: Inf
Inf
Inf
NaN
NaN
左側のオペランド: NaN
NaN
NaN
NaN
NaN
表 G-20  比較結果
右側のオペランド: 0
右側のオペランド: +Num
右側のオペランド: +Inf
右側のオペランド: +NaN
左側のオペランド: 0
=
<
<
Uno
左側のオペランド: +Num
>
比較の結果
<
Uno
左側のオペランド: +Inf
>
>
=
Uno
左側のオペランド: +NaN
Uno
Uno
Uno
Uno

注 - NaN と比較した NaN は順序不定で、結果は不等価になります。+0 は -0 と比較結果が等しくなります。

G.3 引数を渡す仕組み

本セクションでは ISO C における引数の渡し方について説明します。

  • C の関数への引数は、すべて値渡しされます。

  • 実引数は関数の宣言において宣言されるのと逆の順序で渡されます。

  • 式である実引数は、関数参照の前に評価されます。その後、式の結果がレジスタに置かれるかスタックにプッシュされます。

G.3.1 32 ビット SPARC

関数は integer 型の結果をレジスタ %o0 に、float 型の結果wpレジスタ %f0 に、double 型の結果をレジスタ %f0%f1 に返します。

long long 型整数は、上位ワード順序は %oN、下位ワード順序は %o(N+1) でレジスタに渡されます。レジスタ内の結果は同様の順序で %o0%o1 に返されます。

double および long double を除くすべての引数は 4 バイトの値として渡されます。double は 8 バイトの値として渡されます。先頭 6 個の 4 バイト値 (double を 8 と数える) は %o0 から %o5 までのレジスタに渡されます。残りはスタック経由で渡されます。構造体の場合は、構造体のコピーが作成され、ポインタがそのコピーに渡されます。long double は構造体と同様の方法で渡されます。

前述のレジスタは、呼び出し側から見えます。

G.3.2 64 ビット SPARC

すべての整数の引数は、8 バイト値として引き渡されます。

浮動小数点引数は可能なかぎり、浮動小数点レジスタに渡されます。

G.3.3 x86/x64

Intel 386 psABI および AMD64 psABI を遵守しています。

関数は次のレジスタで結果を返します。

表 G-21  型を返すために x86 関数が使用するレジスタ (-m32)
返される型
レジスタ
int
%eax
long long
%edx%eax
floatdoublelong double
%st(0)
float _Complex
%eax (実数部) と %edx (虚数部)
double _Complexlong double _Complex
対応する浮動小数点型の 2 つの要素を含む構造体と同じ

詳細は、http://www.x86-64.org/documentation/abi.pdfhttp://www.x86–64.org/documentation/abi.pdf で AMD64 psABI についての説明を参照してください。

structunionlong longdoublelong double を除くすべての引数は 4 バイト値として渡されます。long long は 8 バイト値として渡され、double は 8 バイト値として渡され、long double は 12 バイト値として渡されます。

structunion はスタックにコピーされます。サイズは 4 の倍数バイトに丸められます。structunion を返す関数には、その structunion を格納する場所を指す隠された最初の引数が渡されます。

関数から戻ったあと、呼び出された関数によってポップされる structunion の余分な引数を除き、スタックから引数をポップするのは呼び出し側の責任です。