Appendix F ISO C Data Representations
This appendix describes how ISO C represents data in storage and the
mechanisms for passing arguments to functions. It is intended 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.
F.1 Storage Allocation
The following table shows the data types and how they are represented.
Note –
Storage allocated on the stack (identifiers with internal,
or automatic, linkage) should be limited to two gigabytes or less.
Table F–1 Storage Allocation for Data Types
|
Data Type
|
Internal Representation
|
|
char elements
|
A single 8-bit byte aligned on a byte boundary.
|
|
short integers
|
Halfword (two bytes or 16 bits), aligned on a two-byte boundary
|
|
int
|
32 bits (four bytes or one word), aligned on a four-byte boundary
|
|
long
|
32 bits on v8 and x86 (four bytes or one word), aligned on a four-byte
boundary
64 bits on v9 (eight bytes or two words) aligned on an eight-byte boundary)
|
|
pointer
|
32 bits on v8 and x86 (four bytes or one word), aligned on a four-byte
boundary
64 bits on v9 (eight bytes or two words) aligned on an eight-byte boundary)
|
|
long long [long long is not available in -Xc mode
with -xc99=none.]
|
(SPARC) 64 bits (eight bytes or two words), aligned on an eight-byte
boundary
(x86) 64 bits (eight bytes or two words), aligned
on a four-byte boundary
|
|
float
|
32 bits (four bytes or one word), aligned on a four-byte boundary. A float has a sign bit, 8-bit exponent, and 23-bit
fraction.
|
|
double
|
64 bits (eight bytes or two words), aligned on an eight-byte boundary
(SPARC) or aligned on a four-byte boundary (x86). A double element has a sign bit, an 11-bit exponent
and a 52-bit fraction.
|
|
long double
|
v8 (SPARC) 128 bits (16 bytes or four words), aligned on an eight-byte
boundary. A long double element has
a sign bit, a 15-bit exponent and a 112-bit fraction.
v9 (SPARC) 128 bits (16 bytes or four words), aligned on a 16 byte boundary.
A long double element has a sign bit,
a 15-bit exponent and a 112-bit fraction.
(x86) 96 bits (12 bytes or three words) aligned
on a four-byte boundary. A long double element
has a sign bit, a 16-bit exponent, and a 64-bit fraction.
16 bits are unused.
|
F.2 Data Representations
Bit numbering of any given data element depend on the architecture in
use: SPARCstationTM 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.
F.2.1 Integer Representations
Integer types used in ISO C are short, int, long, and long long:
Table F–2 Representation of
short
|
Bits
|
Content
|
|
8- 15
|
Byte 0 (SPARC)
Byte 1 (x86)
|
|
0- 7
|
Byte 1 (SPARC)
Byte 0 (x86)
|
Table F–3 Representation of
int
|
Bits
|
Content
|
|
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 F–4 Representation of
long on x86
and SPARC v8 versus SPARC v9
|
Bits
|
Content
|
|
24- 31
|
Byte 0 (SPARC) v8
Byte 4 (SPARC) v9
Byte 3 (x86)
|
|
16- 23
|
Byte 1 (SPARC) v8
Byte 5 (SPARC) v9
Byte 2 (x86)
|
|
8- 15
|
Byte 2 (SPARC) v8
Byte 6 (SPARC) v9
Byte 1 (x86)
|
|
0- 7
|
Byte 3 (SPARC) v8
Byte 7 (SPARC) v9
Byte 0 (x86)
|
Note –
long long is not available in -Xc mode.
Table F–5 Representation of
long long
|
Bits
|
Content
|
|
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)
|
F.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(e- bias)¥2 j.f
where:
-
s = sign
-
e = 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.
The following tables show the position of the bits.
Table F–6
float Representation
|
Bits
|
Name
|
|
31
|
Sign
|
|
23- 30
|
Exponent
|
|
0- 22
|
Fraction
|
Table F–7
double Representation
|
Bits
|
Name
|
|
63
|
Sign
|
|
52- 62
|
Exponent
|
|
0- 51
|
Fraction
|
Table F–8
long double Representation
(SPARC)
|
Bits
|
Name
|
|
127
|
Sign
|
|
112- 126
|
Exponent
|
|
0- 111
|
Fraction
|
Table F–9
long double Representation
(x86)
|
Bits
|
Name
|
|
80- 95
|
Unused
|
|
79
|
Sign
|
|
64- 78
|
Exponent
|
|
63
|
Leading bit
|
|
0- 62
|
Fraction
|
For further information, refer to the Numerical Computation
Guide.
F.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 F–10
float Representations
|
normal number (0<e<255):
|
(-1)Sign2 (exponent-
127)1.f
|
|
subnormal number
(e=0, f!=0):
|
(-1)Sign2 (-126)0.f
|
|
zero (e=0, f=0):
|
(-1)Sign0.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 F–11
double Representations
|
normal number (0<e<2047):
|
(-1)Sign2 (exponent-
1023)1.f
|
|
subnormal number (e=0, f!=0):
|
(-1)Sign2 (-1022)0.f
|
|
zero (e=0, f=0):
|
(-1)Sign0.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 F–12
long double Representations
|
normal number (0<e<32767):
|
(-1)Sign2 (exponent-
16383)1.f
|
|
subnormal number (e=0, f!=0):
|
(-1)Sign2 (-16382)0.f
|
|
zero (e=0, f=0):
|
(-1)Sign0.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)
|
F.2.4 Hexadecimal Representation of Selected Numbers
The following tables show the hexadecimal representations.
Table F–13 Hexadecimal Representation of Selected Numbers (SPARC)
|
Value
|
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
|
|
+Infinity
-Infinity
|
7F800000
FF800000
|
7FF0000000000000
FFF0000000000000
|
7FFF00000000000000000000000000000
FFFF00000000000000000000000000000
|
|
NaN
|
7FBFFFFF
|
7FF7FFFFFFFFFFFF
|
7FFF7FFFFFFFFFFFFFFFFFFFFFFFFFFF
|
Table F–14 Hexadecimal Representation of Selected Numbers
(x86)
|
Value
|
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
|
|
+Infinity
-Infinity
|
7F800000
FF800000
|
000000007FF00000
00000000FFF00000
|
7FFF8000000000000000
FFFF8000000000000000
|
|
NaN
|
7FBFFFFF
|
FFFFFFFF7FF7FFFF
|
7FFFBFFFFFFFFFFFFFFF
|
For further information, refer to the Numerical Computation
Guide.
F.2.5 Pointer Representation
A pointer in C occupies four bytes. A pointer in C occupies eight bytes
on SPARC v9 architectures. The NULL value pointer is equal
to zero.
F.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 simply 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 F.1 Storage Allocation for information
on the size limit of storage allocated on the stack.
Table F–15 Array Types and Storage
|
Type
|
Maximum Number of Elements for SPARC and x86
|
Maximum Number of Elements for SPARC V9
|
|
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 [Not valid in -Xc mode with -xc99=none.]
|
536,870,911
|
288,230,376,151,711,743
|
Static and global arrays can accommodate many more elements.
F.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 F–16 Abbreviation Usage
|
Abbreviation
|
Meaning
|
|
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 F–17 Addition and Subtraction Results
|
|
Right Operand: 0
|
Right Operand: Num
|
Right Operand: Inf
|
Right Operand: NaN
|
|
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 F–18 Multiplication Results
|
|
Right Operand:0
|
Right Operand:Num
|
Right Operand:Inf
|
Right Operand:NaN
|
|
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 F–19 Division Results
|
|
Right Operand:0
|
Right Operand:Num
|
Right Operand:Inf
|
Right Operand:NaN
|
|
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 F–20 Comparison Results
|
|
Right Operand:0
|
Right Operand:+Num
|
Right Operand:+Inf
|
Right Operand:+NaN
|
|
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.
F.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 which are expressions are evaluated before
the function reference. The result of the expression is then placed in a register
or pushed onto the stack.
F.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 doubles and long doubles, are
passed as four-byte values. A double is passed as an eight-byte
value. The first six four-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.
F.3.1.1 64-Bit SPARC
All integral arguments are passed as eight-byte values.
Floating-point arguments are passed in floating-point registers when
possible.
(x86)
Functions return results in the following registers:
Table F–21 Registers Used by x86 Functions to Return Types
|
Register
|
Type Returned
|
|
int
|
%eax
|
|
long long
|
%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.
|
All arguments except structs, unions, long longs, doubles and long doubles are passed as four-byte values;
a long long is passed as an eight-byte
value, a double is passed as an eight-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, it is the responsibility of the caller
to pop arguments from the stack, except for the extra argument for struct and union returns that is popped by the called
function.