ISO C 数据表示法
本附录介绍了 ISO C 如何表示存储器中的数据以及向函数传递参数的机制。它可以为想要编写或使用非 C 语言模块并将这些模块与 C 代码连接的程序员提供指导。
G.1 存储分配
下表显示了数据类型及其表示方法。大小以字节为单位。
注 - 堆栈中分配
的存储空间(带有内部、自动或链接的标识符)应限于 2G 字节或更少。
表 G-1 数据类型的存储分配 | | | | |
整数
|
_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)
|
指针
|
any-type * any-type (*) ()
| 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 中使用的整型有 short、int、long 和 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 浮点表示法
float、double 和 long double 数据元素按照 ISO IEEE 754-1985 标准来表示。表示法为:
(-1)s *2(e - bias) *[j.f]
其中:
对于 IEEE Single 和 Double,j 总是隐式的。偏置指数为 0 时, j 为 0,只要 f 不为 0,生成的数字就不太正常。偏置指数大于 0 时,只要该数字是有限的,j 就为 1。
对于 Intel 80 位 Extended,j 总是显式的。
下表显示各个位的位置。
表 G-6 float 表示法 | |
31
| 符号
|
23- 30
| 偏置指数
|
0- 22
| 尾数部分
|
|
表 G-7 double 表示法 | |
63
| 符号
|
52- 62
| 偏置指数
|
0- 51
| 尾数部分
|
|
表 G-8 long double 表示法 (SPARC) | |
127
| 符号
|
112- 126
| 偏置指数
|
0- 111
| 尾数部分
|
|
表 G-9 long double 表示法 (x86) | |
80- 95
| 不使用
|
79
| 符号
|
64- 78
| 偏置指数
|
63
| 前导位
|
0- 62
| 尾数部分
|
|
有关详细信息,请参阅《数值计算指南》。
G.2.3 异常值
float 和 double 数被认为包含一个“隐藏的”或隐含的位,从而比不包含该位时的精度高一位。对于 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(max);f=.0uuu-uu;至少一个位必须为非零
|
静态 NaN
| s=u,e=255(max);f=.1uuu-uu
|
无穷
| s=u,e=255(max);f=.0000-00(全为零)
|
|
表 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(max);f=.0uuu-uu;至少一个位必须为非零
|
静态 NaN
| s=u,e=2047(max);f=.1uuu-uu
|
无穷
| s=u,e=2047(max);f=.0000-00(全为零)
|
|
表 G-12 long double 表示法正规数 (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(max);f=.0uuu-uu;至少一个位必须为非零
|
静态 NaN
| s=u,e=32767(max);f=.1uuu-uu
|
无穷
| s=u,e=32767(max);f=.0000-00(全为零)
|
|
G.2.4 选定的数的十六进制表示
下表显示十六进制表示。
表 G-13 选定数的十六进制表示法 (SPARC) | | | |
+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 选定数的十六进制表示法 (x86) | | | |
+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 数组类型和存储 | | |
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
| 0
| Num
| Inf
| NaN
|
左操作数: Num
| Num
| 请参见 结果太大(溢出)时,Num + Num 可能为 Inf 而不是 Num。无穷值具有相反的 sign 时,Inf + Inf = NaN。
| Inf
| NaN
|
左操作数: Inf
| Inf
| Inf
| 请参见
| NaN
|
左操作数: NaN
| NaN
| NaN
| NaN
| NaN
|
|
表 G-18 乘法结果 | | | | |
左操作数: 0
| 0
| 0
| NaN
| NaN
|
左操作数: Num
| 0
| Num
| Inf
| NaN
|
左操作数: Inf
| NaN
| Inf
| Inf
| NaN
|
左操作数: NaN
| NaN
| NaN
| NaN
| NaN
|
|
表 G-19 除法结果 | | | | |
左操作数: 0
| NaN
| 0
| 0
| NaN
|
左操作数: Num
| Inf
| Num
| 0
| NaN
|
左操作数: Inf
| Inf
| Inf
| NaN
| NaN
|
左操作数: NaN
| NaN
| NaN
| NaN
| NaN
|
|
表 G-20 比较结果 | | | | |
左操作数: 0
| =
| <
| <
| Uno
|
左操作数: +Num
| >
| 比较的结果
| <
| Uno
|
左操作数: +Inf
| >
| >
| =
| Uno
|
左操作数: +NaN
| Uno
| Uno
| Uno
| Uno
|
|
注 - NaN 与 NaN 比较结果为无序,从而导致不相等。+0 与 - 0 的比较结果是相等。
G.3 参数传递机制
本节介绍了在 ISO C 中如何传递参数。
G.3.1 32 位 SPARC
函数在寄存器 %o0 中返回 integer 结果,在寄存器 %f0 中返回 float 结果,在寄存器 %f0 和 %f1 中返回 double 结果。
long long 整数以较高词序在 %oN 寄存器中进行传递,以较低词序在 %o(N+1) 寄存器中进行传递。寄存器中的结果在 %o0 和 %o1 中返回,排序相似。
除 doubles 和 long double 外,所有参数都作为 4 字节值来传递。double 作为 8 字节值传递。前六个 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
|
|
%edx 和 %eax
|
float、double 和 long double
|
%st(0)
|
float _Complex
|
实部为 %eax,虚部为 %edx
|
double _Complex 和 long double _Complex
|
与包含相应浮点类型的两个元素的结构相同。
|
|
有关详细信息,请参阅 http://www.x86-64.org/documentation/abi.pdfhttp://www.x86–64.org/documentation/abi.pdf 上的 AMD64 psABI
除了 struct、union、long long、double 和 long double 之外的所有参数都作为 4 字节值传递;long long 作为 8 字节值传递,double 作为 8 字节值传递,long double 作为 12 字节值传递。
struct 和 union 被复制到堆栈中。大小向上舍入为 4 字节的倍数。返回 struct 和 union 的函数被传递一个隐藏的首参数,并指向返回的 struct 或 union 的存储位置。
从一个函数返回时,调用程序负责从堆栈中弹出参数,但 struct 和 union 返回的附加参数除外,它由调用的函数弹出。