Previous Next Contents Index Doc Set Home


ANSI C Data Representations

A


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.


Storage Allocation

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 (four bytes or one word), aligned on a four-byte boundary

long long1

(SPARC) (PowerPC) 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) (PowerPC) 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

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

(PowerPC) 128 bits (16 bytes or four words), aligned on a16-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.

1 long long is not available in -Xc mode.


Data Representations

Bit numberings 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.

Integer 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) (PowerPC)

0 - 7

Byte 1 (SPARC)

Byte 0 (Intel) (PowerPC)



Table  A-3 Representation of int and long
Bits
Content

24 - 31

Byte 0 (SPARC)

Byte 3 (Intel) (PowerPC)

16 - 23

Byte 1 (SPARC)

Byte 2 (Intel) (PowerPC)

8 - 15

Byte 2 (SPARC)

Byte 1 (Intel) (PowerPC)

0 - 7

Byte 3 (SPARC)

Byte 0 (Intel) (PowerPC)



Table  A-4 Representation of long long1 
Bits
Content

56 - 63

Byte 0 (SPARC)

Byte 7 (Intel) (PowerPC)

48 - 55

Byte 1 (SPARC)

Byte 6 (Intel) (PowerPC)

40 - 47

Byte 2 (SPARC)

Byte 5 (Intel) (PowerPC)

32 - 39

Byte 3 (SPARC)

Byte 4 (Intel) (PowerPC)

24 - 31

Byte 4 (SPARC)

Byte 3 (Intel) (PowerPC)

16 - 23

Byte 5 (SPARC)

Byte 2 (Intel) (PowerPC)

8 - 15

Byte 6(SPARC)

Byte 1 (Intel) (PowerPC)

0 - 7

Byte 7 (SPARC)

Byte 0 (Intel) (PowerPC)

1 long long is not available in -Xc mode.

Floating-Point Representations

float, double, and long double data elements are represented according to the ANSI IEEE 754-1985 standard. The representation is:

(-1)s2(e - bias) × j.f
where:

The following tables show the position of the bits.

Table  A-5 float Representation 
Bits
Name

31

Sign

23 - 30

Exponent

0 - 22

Fraction



Table  A-6 double Representation
Bits
Name

63

Sign

52 - 62

Exponent

0 - 51

Fraction



Table  A-7 long double Representation (SPARC) (PowerPC)
Bits
Name

127

Sign

112 - 126

Exponent

0 - 111

Fraction



Table  A-8 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.

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) (PowerPC) or explicit (Intel); this bit is 1 for normal numbers, and 0 for subnormal numbers.

Table  A-9 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-10 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-11 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)

Hexadecimal Representation of Selected Numbers

The following tables show the hexadecimal representations.

Table  A-12 Hexadecimal Representation of Selected Numbers (SPARC) (PowerPC)  
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-13 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.

Pointer Representation

A pointer in C occupies four bytes. The NULL value pointer is equal to zero.

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.

Table  A-14 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) (PowerPC)

22369621 (Intel)

long long1

33554431

1 Not valid in -Xc mode

Static and global arrays can accommodate many more elements.

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 tables explain the abbreviations:

Table  A-15 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-16 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


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

Table  A-17 Multiplication Results

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-18 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-19 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



Note - NaN compared with NaN is unordered, and results in inequality. +0 compares equal to -0.


Argument-Passing Mechanism

This section describes how arguments are passed in ANSI 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 long1 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.

(PowerPC)

Functions return integer results in register %r3. Float and double results are returned in %f1. For float results, the value returned is rounded to float precision. Long long and structure or union result whose size is 8 bytes or less are returned in registers %r3 and %r4, with %r3 containing the low-addressed word of the structure as stored in memory. For other structures or unions and long double results, the caller passes a pointer to a storage area into which the result is copied in register %r3 as an implicit first argument.

Arguments are passed in integer registers %r3 through %r10, floating-point registers %f1 through %f8 and a parameter area on the stack. All arguments except doubles, long doubles, and long long are passed as four-byte values.

In the description of the argument-passing algorith below, gr is the number of the next integer register to be used for argument passing, fr is the number of the next floating point register, and starg is a pointer to the next word in the parameter area.

INITIALIZE:
Set fr=1, gr=3, and starg to the start of the parameter area.

SCAN:
If there are no more arguments, terminate. Otherwise, select one of the following, depending on the type of the next argument:

DOUBLE_OR_FLOAT:
If fr>8 (that is, there are no more available floating-point registers), go to OTHER. Otherwise, load the argument value into floating register fr, increment fr, and go to SCAN.

SIMPLE_ARG:
A SIMPLE_ARG is one of the following:
1. One of the simple integer types no more than 32 bits wide (char, short, int, long, enum), or
2. A pointer to an object of any type, or
3. A structure, union, or long double, is passed as a pointer to a copy of the object made by the caller.

If gr>10, go to OTHER. Otherwise, load the argument value into general register gr, set gr to gr+1, and go to SCAN. Values shorter than 32 bits are sign extended or zero extended depending on whether they are signed or unsigned.

LONG_LONG:
If gr>7, go to OTHER. If gr is even, set gr to gr+1. Load the lower-addressed word of the long long into gr and the higher-addressed word into gr+1, increment gr by 2 and to SCAN.

OTHER:
Arguments not otherwise handled above are passed in the parameter words of the caller's stack frame. Integer values shorter than 32 bits are (conceptually) sign or zero extended to 32 bits and considered to have 4-byte size and alignment; otherwise the size, sz, of the argument is as determined by the sizeof operator. Round starg up to a multiple of the alignment requirement of the argument and copy the argument byte-for-byte, beginning with its lowest addressed byte, into starg, ..., starg+sz-1. Set starg to starg+sz, then go to SCAN.


Previous Next Contents Index Doc Set Home


1 Not available in -Xc mode.