This appendix describes how ANSI 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 to C code.
Table A-1 shows the data types and how they are represented.
Table A-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 and long |
32 bits on v8 (four bytes or one word), aligned on a four-byte boundary 64 bits on v9 (four bytes or one word) aligned on an eight-byte boundary) |
(SPARC) 64 bits (eight bytes or two words), aligned on an eight-byte boundary (Intel) 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 (Intel). 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.
(Intel) 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. |
Bit numberings of any given data element depend on the architecture in use: SPARCstation(TM) 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.
Integer types used in ANSI C are short, int, long, and long long:
Table A-2 Representation of short
Bits |
Content |
---|---|
8 - 15 |
Byte 0 (SPARC) Byte 1 (Intel) |
0 - 7 |
Byte 1 (SPARC) Byte 0 (Intel) |
Table A-3 Representation of int
Bits |
Content |
---|---|
24 - 31 |
Byte 0 (SPARC) Byte 3 (Intel) |
16 - 23 |
Byte 1 (SPARC) Byte 2 (Intel) |
8 - 15 |
Byte 2 (SPARC) Byte 1 (Intel) |
0 - 7 |
Byte 3 (SPARC) Byte 0 (Intel) |
Table A-4 Representation of long on Intel and SPARC v8 versus SPARC v9
Bits |
Content |
---|---|
24 - 31 |
Byte 0 (SPARC) v8 Byte 4 (SPARC) v9 Byte 3 (Intel) |
16 - 23 |
Byte 1 (SPARC) v8 Byte 5 (SPARC) v9 Byte 2 (Intel) |
8 - 15 |
Byte 2 (SPARC) v8 Byte 6 (SPARC) v9 Byte 1 (Intel) |
0 - 7 |
Byte 3 (SPARC) v8 Byte 7 (SPARC) v9 Byte 0 (Intel) |
Table A-5 Representation of long long [long long is not available in -Xc mode.]
Bits |
Content |
---|---|
56 - 63 |
Byte 0 (SPARC) Byte 7 (Intel) |
48 - 55 |
Byte 1 (SPARC) Byte 6 (Intel) |
40 - 47 |
Byte 2 (SPARC) Byte 5 (Intel) |
32 - 39 |
Byte 3 (SPARC) Byte 4 (Intel) |
24 - 31 |
Byte 4 (SPARC) Byte 3 (Intel) |
16 - 23 |
Byte 5 (SPARC) Byte 2 (Intel) |
8 - 15 |
Byte 6(SPARC) Byte 1 (Intel) |
0 - 7 |
Byte 7 (SPARC) Byte 0 (Intel) |
float, double, and long double data elements are represented according to the ANSI/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 (Intel), 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 A-6 float Representation
Bits |
Name |
---|---|
31 |
Sign |
23 - 30 |
Exponent |
0 - 22 |
Fraction |
Table A-7 double Representation
Bits |
Name |
---|---|
63 |
Sign |
52 - 62 |
Exponent |
0 - 51 |
Fraction |
Table A-8 long double Representation (SPARC)
Bits |
Name |
---|---|
127 |
Sign |
112 - 126 |
Exponent |
0 - 111 |
Fraction |
Table A-9 long double Representation (Intel)
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.
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 (Intel); this bit is 1 for normal numbers, and 0 for subnormal numbers.
Table A-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 A-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 A-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) |
The following tables show the hexadecimal representations.
Table A-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 A-14 Hexadecimal Representation of Selected Numbers (Intel)
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.
A pointer in C occupies four bytes. The NULL value pointer is equal to zero.
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.
Table A-15 Automatic Array Types and Storage
Type |
Maximum Number of Elements |
---|---|
char |
268435455 |
short |
134217727 |
int |
67108863 |
long |
67108863 |
float |
67108863 |
double |
33554431 |
long double |
1677215 (SPARC) 22369621 (Intel) |
33554431 |
Static and global arrays can accommodate many more elements.
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 tables explain the abbreviations:
Table A-16 Abbreviation Usage
Abbreviation |
Meaning |
---|---|
Num |
Subnormal or normal number |
Inf |
Infinity (positive or negative) |
NaN |
Not a number |
Uno |
Unordered |
The tables that follow describe the types of values that result from arithmetic operations performed with combinations of different types of operands.
Table A-17 Addition and Subtraction Results
Right Operand |
||||
Left Operand |
0 |
Num |
Inf |
NaN |
0 |
0 |
Num |
Inf |
NaN |
Num |
Num |
See Note |
Inf |
NaN |
Inf |
Inf |
Inf |
See Note |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
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.
|
Right Operand |
|||
Left Operand |
0 |
Num |
Inf |
NaN |
0 |
0 |
0 |
NaN |
NaN |
Num |
0 |
Num |
Inf |
NaN |
Inf |
NaN |
Inf |
Inf |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Table A-19 Division Results
|
Right Operand |
|||
Left Operand |
0 |
Num |
Inf |
NaN |
0 |
NaN |
0 |
0 |
NaN |
Num |
Inf |
Num |
0 |
NaN |
Inf |
Inf |
Inf |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Table A-20 Comparison Results
|
Right Operand |
|||
Left Operand |
0 |
+Num |
+Inf |
NaN |
0 |
= |
< |
< |
Uno |
+Num |
> |
The result of the comparison |
< |
Uno |
+Inf |
> |
> |
= |
Uno |
NaN |
Uno |
Uno |
Uno |
Uno |
NaN compared with NaN is unordered, and results in inequality. +0 compares equal to -0.
This section describes how arguments are passed in ANSI/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.
(SPARC)
Functions return integer results in register %o0, float results in register %f0, and double results in registers %f0 and %f1.
long long [Not available in -Xc mode.] 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 %i0 and %i1, 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.
Upon return from a function, it is the responsibility of the caller to pop arguments from the stack. Registers described are as seen by the caller.
(Intel)
Functions return integer results in register %eax.
long long results are returned in registers %edx and %eax. Functions return float, double, and long double results in register %st(0).
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.