Oracle® Solaris Studio 12.4: C User's Guide

Exit Print View

Updated: March 2015
 
 

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
C Type
LP64 (-m64) size
LP64 alignment
ILP32 (-m32) size
ILP 32 alignment
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
Bits
Content
8- 15
Byte 0 (SPARC)
Byte 1 (x86)
0- 7
Byte 1 (SPARC)
Byte 0 (x86)
Table G-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 G-4  Representation of long Compiled with -m32
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 G-5  Representation of long (-m64) and long long (both -m32 and -m64)
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)

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
Bits
Name
31
sign
23- 30
biased exponent
0- 22
fraction
Table G-7  double Representation
Bits
Name
63
sign
52- 62
biased exponent
0- 51
fraction
Table G-8  longdouble Representation (SPARC)
Bits
Name
127
sign
112- 126
biased exponent
0- 111
fraction
Table G-9  longdouble Representation (x86)
Bits
Name
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 Representations
normal 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 Representations
normal 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  longdouble Representations
normal 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)
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 G-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.

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
Type
Maximum Number of Elements for -m32
Maximum Number of Elements for -m64
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
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 G-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 G-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 G-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 G-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.

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)
Type Returned
Register
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.

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.