ISO C Data Representations
This appendix describes how ISO C represents data in storage and the
mechanisms for passing arguments to functions. It can serve as a guide to
programmers who want to write or use modules in languages other than C and
have those modules interface with C code.
G.1 Storage Allocation
The following table shows the data types and how they are represented. Sizes
are in bytes.
Note - Storage allocated
on the stack (identifiers with internal,
or automatic, linkage) should be limited to 2 gigabytes or less.
Table G-1 Storage Allocation for Data Types | | | | |
Integer
|
_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)
|
Pointer
|
any-type * any-type (*) ()
| 8
| 8
| 4
| 4
|
Floating Point
|
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)
|
Complex
|
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)
|
Imaginary
|
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 Data Representations
Bit numbering of any given data element depends on the architecture
in use: SPARCstation machines use bit 0 as the least
significant bit, with byte 0 being the most significant byte. The tables in
this section describe the various representations.
G.2.1 Integer Representations
Integer types used in ISO C are short, int, long, and long long:
Table G-2 Representation of short | |
8- 15
| Byte 0 (SPARC) Byte 1 (x86)
|
0- 7
| Byte 1 (SPARC) Byte 0 (x86)
|
|
Table G-3 Representation of int | |
24- 31
| Byte 0 (SPARC) Byte 3 (x86)
|
16- 23
| Byte 1 (SPARC) Byte 2 (x86)
|
8- 15
| Byte 2 (SPARC) Byte 1 (x86)
|
0- 7
| Byte 3 (SPARC) Byte 0 (x86)
|
|
Table G-4 Representation of long Compiled
with -m32 | |
24- 31
| Byte 0 (SPARC) Byte 3 (x86)
|
16- 23
| Byte 1 (SPARC) Byte 2 (x86)
|
8- 15
| Byte 2 (SPARC) Byte 1 (x86)
|
0- 7
| Byte 3 (SPARC) Byte 0 (x86)
|
|
Table G-5 Representation of long (-m64) and long long (both -m32 and -m64)
| |
56- 63
| Byte 0 (SPARC) Byte 7 (x86)
|
48- 55
| Byte 1 (SPARC) Byte 6 (x86)
|
40- 47
| Byte 2 (SPARC) Byte 5 (x86)
|
32- 39
| Byte 3 (SPARC) Byte 4 (x86)
|
24- 31
| Byte 4 (SPARC) Byte 3 (x86)
|
16- 23
| Byte 5 (SPARC) Byte 2 (x86)
|
8- 15
| Byte 6 (SPARC) Byte 1 (x86)
|
0- 7
| Byte 7 (SPARC) Byte 0 (x86)
|
|
G.2.2 Floating-Point Representations
float, double, and long double data elements are represented according to the ISO IEEE 754-1985
standard. The representation is:
(-1)s *2(e - bias) *[j.f]
where:
s is the sign
e is the biased exponent
j is the leading bit, determined
by the value of e. In the case of long double (x86), the leading bit is explicit;
in all other cases, it is implicit.
f = fraction
u means that the bit can be either
0 or 1 (used in the tables in this section).
For IEEE Single and Double, j is always implicit.
When the biased exponent is 0, j is 0, and the
resulting number is subnormal as long as f is
not 0. When the biased exponent is greater than 0, j is
1 as long as the number is finite.
For Intel 80–bit Extended, j is always
explicit.
The following tables show the position of the bits.
Table G-6 float Representation | |
31
| sign
|
23- 30
| biased exponent
|
0- 22
| fraction
|
|
Table G-7 double Representation | |
63
| sign
|
52- 62
| biased exponent
|
0- 51
| fraction
|
|
Table G-8 long double Representation
(SPARC) | |
127
| sign
|
112- 126
| biased exponent
|
0- 111
| fraction
|
|
Table G-9 long double Representation
(x86) | |
80- 95
| not used
|
79
| sign
|
64- 78
| biased exponent
|
63
| leading bit
|
0- 62
| fraction
|
|
For further information, refer to the Numerical Computation
Guide.
G.2.3 Exceptional Values
float and double numbers are said
to contain a “hidden,” or implied, bit, providing for one more
bit of precision than would otherwise be the case. In the case of long double, the leading bit is implicit (SPARC) or explicit (x86);
this bit is 1 for normal numbers, and 0 for subnormal numbers.
Table G-10 float Representationsnormal number (0<e<255):
| (-1)s2 (e-127)1.f
|
subnormal number (e=0, f!=0):
| (-1)s2 (-126)0.f
|
zero (e=0, f=0):
| (-1)s0.0
|
signaling NaN
| s=u, e=255(max); f=.0uuu-uu; at least one bit must be nonzero
|
quiet NaN
| s=u, e=255(max); f=.1uuu-uu
|
Infinity
| s=u, e=255(max); f=.0000-00 (all zeroes)
|
|
Table G-11 double Representationsnormal number (0<e<2047):
| (-1)s2 (e-1023)1.f
|
subnormal number (e=0, f!=0):
| (-1)s2 (-1022)0.f
|
zero (e=0, f=0):
| (-1)s0.0
|
signaling NaN
| s=u, e=2047(max); f=.0uuu-uu; at least one bit must be nonzero
|
quiet NaN
| s=u, e=2047(max); f=.1uuu-uu
|
Infinity
| s=u, e=2047(max); f=.0000-00 (all zeroes)
|
|
Table G-12 long double Representationsnormal number (0<e<32767):
| (-1)s2 (e-
16383)1.f
|
subnormal number (e=0, f!=0):
| (-1)s2 (-16382)0.f
|
zero (e=0, f=0):
| (-1)s0.0
|
signaling NaN
| s=u, e=32767(max); f=.0uuu-uu; at least one bit must be nonzero
|
quiet NaN
| s=u, e=32767(max); f=.1uuu-uu
|
Infinity
| s=u, e=32767(max); f=.0000-00 (all zeroes)
|
|
G.2.4 Hexadecimal Representation of Selected Numbers
The following tables show the hexadecimal representations.
Table G-13 Hexadecimal Representation of Selected Numbers (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
|
+Infinity -Infinity
| 7F800000 FF800000
| 7FF0000000000000 FFF0000000000000
| 7FFF00000000000000000000000000000 FFFF00000000000000000000000000000
|
NaN
| 7FBFFFFF
| 7FF7FFFFFFFFFFFF
| 7FFF7FFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
Table G-14 Hexadecimal Representation of Selected Numbers (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
|
+Infinity -Infinity
| 7F800000 FF800000
| 000000007FF00000 00000000FFF00000
| 7FFF8000000000000000 FFFF8000000000000000
|
NaN
| 7FBFFFFF
| FFFFFFFF7FF7FFFF
| 7FFFBFFFFFFFFFFFFFFF
|
|
For further information, refer to the Numerical Computation
Guide.
G.2.5 Pointer Representation
A pointer in C occupies four bytes. A pointer in C occupies 8 bytes
on 64–bit SPARC v9 architectures. The NULL value
pointer is equal to zero.
G.2.6 Array Storage
Arrays are stored with their elements in a specific storage order. The
elements are actually stored in a linear sequence of storage elements.
C arrays are stored in row-major order. The last subscript in a multidimensional
array varies the fastest.
String data types are arrays of char elements. The
maximum number of characters allowed in a string literal or wide string literal
(after concatenation) is 4,294,967,295.
See Storage Allocation for information
on the size limit of storage allocated on the stack.
Table G-15 Array Types and Storage | | |
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
|
|
Static and global arrays can accommodate many more elements.
G.2.7 Arithmetic Operations on Exceptional Values
This section describes the results derived from applying the basic arithmetic
operations to combinations of exceptional and ordinary floating-point values.
The information that follows assumes that no traps or any other exception
actions are taken.
The following table explains the abbreviations.
Table G-16 Abbreviation Usage
|
|
Num
|
Subnormal or normal number
|
Inf
|
Infinity (positive or negative)
|
NaN
|
Not a number
|
Uno
|
Unordered
|
|
The following tables describe the types of values that result from arithmetic
operations performed with combinations of different types of operands.
Table G-17 Addition and Subtraction Results | | | | |
Left Operand: 0
| 0
| Num
| Inf
| NaN
|
Left Operand: Num
| Num
| See Num + Num could be Inf, rather than Num, when the result is too large
(overflow). Inf + Inf = NaN when the infinities are of opposite sign.
| Inf
| NaN
|
Left Operand: Inf
| Inf
| Inf
| See
| NaN
|
Left Operand: NaN
| NaN
| NaN
| NaN
| NaN
|
|
Table G-18 Multiplication Results | | | | |
Left Operand:0
| 0
| 0
| NaN
| NaN
|
Left Operand: Num
| 0
| Num
| Inf
| NaN
|
Left Operand: Inf
| NaN
| Inf
| Inf
| NaN
|
Left Operand: NaN
| NaN
| NaN
| NaN
| NaN
|
|
Table G-19 Division Results | | | | |
Left Operand:0
| NaN
| 0
| 0
| NaN
|
Left Operand: Num
| Inf
| Num
| 0
| NaN
|
Left Operand: Inf
| Inf
| Inf
| NaN
| NaN
|
Left Operand: NaN
| NaN
| NaN
| NaN
| NaN
|
|
Table G-20 Comparison Results | | | | |
Left Operand:0
| =
| <
| <
| Uno
|
Left Operand: +Num
| >
| The result of the comparison
| <
| Uno
|
Left Operand: +Inf
| >
| >
| =
| Uno
|
Left Operand: +NaN
| Uno
| Uno
| Uno
| Uno
|
|
Note - NaN compared with NaN is unordered, and results in inequality.
+0 compares equal to –0.
G.3 Argument-Passing Mechanism
This section describes how arguments are passed in ISO C.
All arguments to C functions are passed by value.
Actual arguments are passed in the reverse order from which
they are declared in a function declaration.
Actual arguments that are expressions are evaluated before
the function reference. The result of the expression is then placed in a register
or pushed onto the stack.
G.3.1 32-Bit SPARC
Functions return integer results in register %o0, float results in register %f0,
and double results in registers %f0 and %f1.
long long integers
are passed in registers with the higher word order in %oN,
and the lower order word in %o(N+1). In-register
results are returned in %o0 and %o1,
with similar ordering.
All arguments, except double and long double,
are passed as 4-byte values. A double is passed as an 8-byte
value. The first six 4-byte values (double counts as 8)
are passed in registers %o0 through %o5.
The rest are passed onto the stack. Structures are passed by making a copy
of the structure and passing a pointer to the copy. A long double is passed in the same manner
as a structure.
Registers described are as seen by the caller.
G.3.2 64-Bit SPARC
All integral arguments are passed as 8-byte values.
Floating-point arguments are passed in floating-point registers when
possible.
G.3.3 x86/x64
Intel 386 psABI and AMD64 psABI are observed.
Functions return results in the following registers:
Table G-21 Registers Used by x86 Functions to Return Types (-m32)
|
|
int
|
%eax
|
|
%edx and %eax
|
float, double, and long
double
|
%st(0)
|
float _Complex
|
%eax for the real part and %edx for the imaginary
part
|
double _Complex and long double _Complex
|
The same as a struct that contains two elements of the corresponding floating-point
type.
|
|
Refer to the AMD64 psABI for details at http://www.x86-64.org/documentation/abi.pdfhttp://www.x86–64.org/documentation/abi.pdf
All arguments except structs, unions, long longs, doubles and long doubles are passed as four-byte values;
a long long is passed as an 8-byte value,
a double is passed as an 8-byte value, and a long double is passed as a 12-byte value.
structs and unions are copied
onto the stack. The size is rounded up to a multiple of four bytes. Functions
returning structs and unions are passed
a hidden first argument, pointing to the location into which the returned struct or union is stored.
Upon return from a function, the caller is responsible for popping arguments
from the stack except for the extra argument for struct and union returns that is popped by the called function.