A P P E N D I X  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 Intel (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 Intel (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[1]

(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.



F.2 Data Representations

Bit numbering of any given data element depend on the architecture in use: SPARCstationtrademark 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 (Intel)

0 - 7

Byte 1 (SPARC)

Byte 0 (Intel)


TABLE F-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 F-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 F-5 Representation of long long [2]

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)


   

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:

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 (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.

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 (Intel); 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 (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.

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 Section 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 Intel

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[3]

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[4]

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.

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[5] 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.

64-Bit SPARC

All integral arguments are passed as eight-byte values.

Floating-point arguments are passed in floating-point registers when possible.

(Intel)

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.


1 (TableFootnote) long long is not available in -Xc mode with -xc99=none.
2 (TableFootnote) long long is not available in -Xc mode.
3 (TableFootnote) Not valid in -Xc mode with -xc99=none.
4 (TableFootnote) 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.
5 (Footnote) Not available in -Xc mode with -xc99=none.