Stdint.h

From Wikipedia, the free encyclopedia

The correct title of this article is stdint.h. The initial letter is shown capitalized due to technical restrictions.
C++ Standard Library headers
C Standard Library headers
assert.h
complex.h
ctype.h
errno.h
fenv.h
float.h
inttypes.h
iso646.h
limits.h
locale.h
math.h
setjmp.h
signal.h
stdarg.h
stdbool.h
stddef.h
stdint.h
stdio.h
stdlib.h
string.h
tgmath.h
time.h
wchar.h
wctype.h

stdint.h is a header file that is part of the C99 standard library. It defines certain classes of integer types, preprocessor macros to construct integer literals, and preprocessor defines to query the range of the types at compile time.

Contents

[edit] Background

[edit] Corresponding integer types

The C standard has a notion of "corresponding integer types". Informally, what this means is for any integer type T:

typedef   signed T A;
typedef unsigned T B;

the type A and the type B are said to be corresponding integer types (note: typedef doesn't create a new type, it creates a new identifier as a synonym for the given type). This is important for two reasons:

  • corresponding types are friendly to aliasing and type puns
  • corresponding types have a similar object representation

Both of these combined require code like:

A a = 1;
B b = 1;
*(B*)&a = 0;
*(A*)&b = 0;

to have defined behavior by the standard (as opposed to being undefined in the general case). There are many caveats to how far you can push this, so it's important to actually read the C standard to see what's legal or not (the bulk of this has to deal with padding bits and out of range representations).

[edit] Representation

The C99 standard elaborated the difference between value representations and object representations.

The object representation of an integer consists of 0 or more padding bits, 1 or more value bits[1], and either 0 or 1 sign bits (this doesn't count as a value bit) depending on the signedness of the integer type.

The value representation is a conceptual representation of an integer. The value representation ignores any padding bits and does a (possible) rearrangement to the bits so that the integer is ordered sequentially from most significant value bit to least significant value bit. Most programmers deal with this representation because it allows them easily write portable code by only dealing with -0 and out of range values as opposed to both of those in addition to tricky aliasing rules and trap representations if they choose to deal with the object representation directly.

TODO: talk about precession, width, padding, sizeof, and CHAR_BIT.

[edit] Signed representation

The C standard allows for only three signed integer representations:

[edit] New integer types

  • The types <something>_t and u<something>_t are required to be corresponding integer types.
  • For the types that are marked optional, an implementation must either define both <something>_t and u<something>_t or neither of the two.
  • If a type is of the form [u]<something>N_t (or similarly for a preprocessor define), N must be a positive decimal integer with no leading 0's.

[edit] Exact-width integer types (optional)

These are of the form intN_t and uintN_t.

  • Both types must have no padding bits.
  • intN_t must be a two's complement integer.

An implementation is required to define exact-width integer types for N = 8[2], 16, 32, or 64 if it has any type that matches the above requirements. It is not required to define them for any other N, even if it support appropriate types.

integer limits
intN_t INTN_MIN INTN_MAX
\begin{matrix} -(2^{N-1}) \\ or \\ -0b1 \underbrace{00 \cdots 0} \\ N-1 \end{matrix} \begin{matrix} 2^{N-1}-1 \\ or \\ 0b0 \underbrace{11 \cdots 1} \\ N-1 \end{matrix}
uintN_t UINTN_MAX
0 \begin{matrix}2^{N}-1 \\ or \\ 0b \underbrace{11\cdots1 } \\ N \end{matrix}

[edit] Minimum-width integer types

These are of the form int_leastN_t and uint_leastN_t.

The standard doesn't mandate anything about these types except that their widths must be ≥ N.

An implementation is required to define these for the following N: 8, 16, 32, 64.

INT_LEASTN_MIN INT_LEASTN_MAX UINT_LEASTN_MAX

INTN_C(value) UINTN_C(value)

[edit] Fastest minimum-width integer types

These are of the form int_fastN_t and uint_fastN_t.

The standard doesn't mandate anything about these types except that their widths must be ≥ N. It also leaves it up to the implementor to decide what it means to be a "fast" integer type.

An implementation is required to define these for the following N: 8, 16, 32, 64.

INT_FASTN_MIN INT_FASTN_MAX UINT_FASTN_MAX

[edit] Integers wide enough to hold pointers (optional)

intptr_t uintptr_t

INTPTRN_MIN INTPTRN_MAX UINTPTRN_MAX

[edit] Greatest-width integer types

intmax_t uintmax_t

INTMAXN_MIN INTMAXN_MAX UINTMAXN_MAX

INTMAX_C(value) UINTMAX_C(value)

[edit] Other integer limits

PTRDIFF_MIN PTRDIFF_MAX

SIZE_MAX

WCHAR_MIN WCHAR_MAX

WINT_MIN WINT_MAX

SIG_ATOMIC_MIN SIG_ATOMIC_MAX

[edit] Criticisms and caveats

  • Some (non-conforming) implementations tack C99 support on top of a C89 runtime library. One of the consequences of this is that the new printf and scanf specifiers aren't recognized and will likely lead to something undefined. The typical ways of working around this are:
    • The most common (and the most wrong) way is to use the long or unsigned long types as an intermediate step and pass these types into printf or scanf. This works reasonably well for the exact, minimum, and fast integer types less than 32-bits but may cause trouble with ptrdiff_t and size_t and the types larger than 32-bits, typically on platforms that use 32-bit longs and 64-bit pointers.
    • Not using scanf directly but manually reading in a buffer, calling strto[i|u]max, and then converting it to the desired type. This doesn't help with printing out integers though.
    • Downloading a 3rd-party printf and scanf library that is C99 compatible.
  • The rules for integer rank and corresponding integer types may force implementers to choose the lesser of two-evils in not supporting an integer type, making a bad compromise, or supporting an integer type a non-conforming way.
    • For example, there are machines that either have special support for an extremely large signed integer register or an extremely large unsigned integer register without supporting the other type. An implementation can either choose not to expose this to a C implementation, synthesize a slow type as the corresponding integer type, synthesizing a weird corresponding integer type, or expose the integer to the programmer without setting it to the [u]intmax_t types or synthesizing a corresponding integer type.
  • The [u]intN_t types are a compromise between the desire to have guaranteed two's complement integer types and the desire to have guaranteed types with no padding bits (as opposed to a more fine grained approach which would define more types). Because of the "all or nothing" approach to the [u]intN_t types, an implementation might have to play the same sort of games described above depending on whether they care about speed, programmer convenience, or standards conformance.

[edit] See also

[edit] Footnotes

  1. ^ technically, it actually allows 0 or more value bits, but the only way you can construct this is with a single-bit bit-field of a signed integer
  2. ^ The standard doesn't require this type to be typedefed to a character type

[edit] Downloads

As stdint.h is currently NOT shipped with visual studio c++ products and older c++ compilers, you may want to use some external one.

  • pstdint.h - A cross-platform, free implementation from paul hsieh. (Compilers tested (all with 0 warnings at their highest respective: Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio.net (VC7), Intel C++ 4.0, GNU gcc v3.3.3)
  • stdint.h - This stdint.h may be used with Microsoft compilers only. But it fully C99 compliant and may be used with similar inttypes.h. Tested with Microsoft Visual Studio .NET 2003 and Microsoft Visual Studio .NET 2005.