Arithmetic types
(See also type for type system overview and the list of type-related utilities that are provided by the C library).
Boolean type
Note that conversion to _Bool does not work the same as conversion to other integer types: | (since C99) |
Character types
-
signed char
- type for signed character representation. -
unsigned char
- type for unsigned character representation. Also used to inspect object representations (raw memory). -
char
- type for character representation. Equivalent to eithersigned char
orunsigned char
(which one is implementation-defined and may be controlled by a compiler commandline switch), butchar
is a distinct type, different from bothsigned char
bothunsigned char
Note that the standard library also defines typedef names wchar_t , char16_t, and char32_t (since C11) to represent wide characters.
Integer types
-
short int
(also accessible asshort
, may use the keywordsigned
) -
unsigned short int
(also accessible asunsigned short
) -
int
(also accessible assigned int
) -
unsigned int
(also accessible asunsigned
), the unsigned counterpart ofint
, implementing modulo arithmetic. Suitable for bit manipulations. -
long int
(also accessible aslong
) -
unsigned long int
(also accessible asunsigned long
)
| (since C99) |
Note: as with all type specifiers, any order is permitted: unsigned long long int
and long int unsigned long
name the same type.
The following table summarizes all available integer types and their properties:
Type specifier | Equivalent type | Width in bits by data model | ||||
---|---|---|---|---|---|---|
C standard | LP32 | ILP32 | LLP64 | LP64 | ||
short | short int | at least 16 | 16 | 16 | 16 | 16 |
short int |
||||||
signed short |
||||||
signed short int |
||||||
unsigned short | unsigned short int |
|||||
unsigned short int |
||||||
int | int | at least 16 | 16 | 32 | 32 | 32 |
signed |
||||||
signed int |
||||||
unsigned | unsigned int |
|||||
unsigned int |
||||||
long | long int | at least 32 | 32 | 32 | 32 | 64 |
long int |
||||||
signed long |
||||||
signed long int |
||||||
unsigned long | unsigned long int |
|||||
unsigned long int |
||||||
long long | long long int (C99) | at least 64 | 64 | 64 | 64 | 64 |
long long int |
||||||
signed long long |
||||||
signed long long int |
||||||
unsigned long long | unsigned long long int (C99) |
|||||
unsigned long long int |
Besides the minimal bit counts, the C Standard guarantees that 1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
.
Note: this allows the extreme case in which bytes are sized 64 bits, all types (including char
) are 64 bits wide, and sizeof
returns 1 for every type.
Note: integer arithmetic is defined differently for the signed and unsigned integer types. See arithmetic operators, in particular integer overflows.
Data models
The choices made by each implementation about the sizes of the fundamental types are collectively known as data model. Four data models found wide acceptance:
32 bit systems:
- LP32 or 2/4/4 (int is 16-bit, long and pointer are 32-bit)
- Win16 API
- ILP32 or 4/4/4 (int, long, and pointer are 32-bit);
- Win32 API
- Unix and Unix-like systems (Linux, Mac OS X)
64 bit systems:
- LLP64 or 4/4/8 (int and long are 32-bit, pointer is 64-bit)
- Win64 API
- LP64 or 4/8/8 (int is 32-bit, long and pointer are 64-bit)
- Unix and Unix-like systems (Linux, Mac OS X)
Other models are very rare. For example, ILP64 (8/8/8: int, long, and pointer are 64-bit) only appeared in some early 64-bit Unix systems (e.g. Unicos on Cray).
Note that exact-width integer types are available in <stdint.h> since C99.
Real floating types
C has three types for representing real floating-point values:
-
float
- single precision floating point type. Matches IEEE-754 32 bit floating point type if supported. -
double
- double precision floating point type. Matches IEEE-754 64 bit floating point type if supported -
long double
- extended precision floating point type. Matches IEEE-754 extended floating-point type if supported, otherwise matches some non-standard extended floating-point type as long as its precision is better thandouble
and range is at least as good asdouble
, otherwise matches the typedouble
. Some x86 and x86_64 implementations use the 80-bit x87 floating point type.
Floating-point types may support special values:
- infinity (positive and negative), see
INFINITY
- the negative zero,
-0.0
. It compares equal to the positive zero, but is meaningful in some arithmetic operations, e.g.1.0/0.0 == INFINITY
, but1.0/-0.0 == -INFINITY
) - not-a-number (NaN), which does not compare equal with anything (including itself). Multiple bit patterns represent NaNs, see
nan
,NAN
. Note that C takes no special notice of signalling NaNs (specified by IEEE-754), and treates all NaNs as quiet.
Real floating-point numbers may be used with arithmetic operators + - / * and various mathematical functions from math.h. Both built-in operators and library functions may raise floating-point exceptions and set errno
as described in math_errhandling
.
Floating-point expressions may have greater range and precision than indicated by their types, see FLT_EVAL_METHOD
. Assignment, return, and cast force the range and precision to the one associated with the declared type.
Floating-point expressions may also be contracted, that is, calculated as if all intermediate values have infinite range and precision, see #pragma STDC FP_CONTRACT.
Some operations on floating-point numbers are affected by and modify the state of the floating-point environment (most notably, the rounding direction).
Implicit conversions are defined between real floating types and integer, complex, and imaginary types.
See Limits of floating point types and the math.h library for additional details, limits, and properties of the floating-point types.
Complex floating typesComplex floating types model the mathematical complex numbers, that is the numbers that can be written as a sum of a real number and a real number multiplied by the imaginary unit: a + bi. The three complex types are.
Note: as with all type specifiers, any order is permitted: #include <complex.h> #include <stdio.h> int main(void) { double complex z = 1 + 2*I; z = 1/z; printf("1/(1.0+2.0i) = %.1f%+.1fi\n", creal(z), cimag(z)); } Output: 1/(1.0+2.0i) = 0.2-0.4i
Each complex type has the same object representation and alignment requirements as an array of two elements of the corresponding real type ( float a[4] = {1, 2, 3, 4}; float complex z1, z2; memcpy(&z1, a, sizeof z1); // z1 becomes 1.0 + 2.0i memcpy(&z2, a+2, sizeof z2); // z2 becomes 3.0 + 4.0i Complex numbers may be used with arithmetic operators + - * and /, possibly mixed with imaginary and real numbers. There are many mathematical functions defined for complex numbers in complex.h. Both built-in operators and library functions may raise floating-point exceptions and set Increment and decrement are not defined for complex types. Relational operators are not defined for complex types (there is no notion of "less than") Implicit conversions are defined between complex types and other arithmetic types. In order to support the one-infinity model of complex number arithmetic, C regards any complex value with at least one infinite part as an infinity even if its other part is a NaN, guarantees that all operators and functions honor basic properties of inifinities and provides #include <stdio.h> #include <complex.h> #include <math.h> int main(void) { double complex z = (1 + 0*I) * (INFINITY + I*INFINITY); // textbook formula would give // (1+i0)(∞+i∞) ⇒ (1×∞ – 0×∞) + i(0×∞+1×∞) ⇒ NaN + I*NaN // but C gives a complex infinity printf("%f + i*%f\n", creal(z), cimag(z)); // textbook formula would give // cexp(∞+iNaN) ⇒ exp(∞)×(cis(NaN)) ⇒ NaN + I*NaN // but C gives ±∞+i*nan double complex y = cexp(INFINITY + I*NAN); printf("%f + i*%f\n", creal(y), cimag(y)); } Possible output: inf + i*inf inf + i*nan C also treats multiple infinities so as to preserve directional information where possible, despite the inherent limitations of the Cartesian representation: multiplying the imaginary unit by real infinity gives the correctly-signed imaginary infinity: i × ∞ = i∞. Also, i × (∞ – i∞) = ∞ + i∞ indicates the reasonable quadrant. Imaginary floating typesImaginary floating types model the mathematical imaginary numbers, that is numbers that can be written as a real number multiplied by the imaginary unit: bi The three imaginary types are.
Note: as with all type specifiers, any order is permitted: #include <complex.h> #include <stdio.h> int main(void) { double imaginary z = 3*I; z = 1/z; printf("1/(3.0i) = %+.1fi\n", cimag(z)); } Output: 1/(3.0i) = -0.3i
Each of the three imaginary types has the same object representation and alignment requirement as its corresponding real type ( Note: despite that, imaginary types are distinct and not compatible with their corresponding real types, which prohibits aliasing. Imaginary numbers may be used with arithmetic operators + - * and /, possibly mixed with complex and real numbers. There are many mathematical functions defined for imaginary numbers in complex.h. Both built-in operators and library functions may raise floating-point exceptions and set Increment and decrement are not defined for imaginary types Implicit conversions are defined between imaginary types and other arithmetic types. The imaginary numbers make it possible to express all complex numbers using the natural notation Imaginary types also simplify implementations; multiplication of an imaginary by a complex can be implemented straightforwardly with two multiplications if the imaginary types are supported, instead of four multiplications and two additions. | (since C99) |
Keywords
char
, int
, short
, long
, signed
, unsigned
, float
, double
. _Bool
, _Complex
, _Imaginary
.
Range of values
The following table provides a reference for the limits of common numeric representations. As the C Standard allows any signed integer representation, the table gives both the minimum guaranteed requirements (which correspond to the limits of one's complement or sign-and-magnitude) and the limits of the most commonly used implementation, two's complement. All popular data models (including all of ILP32, LP32, LP64, LLP64) use two's complement representation, though.
Type | Size in bits | Format | Value range | |
---|---|---|---|---|
Approximate | Exact | |||
character | 8 | signed (one's complement) | -127 to 127 | |
signed (two's complement) | -128 to 127 | |||
unsigned | 0 to 255 | |||
integral | 16 | signed (one's complement) | ± 3.27 · 104 | -32767 to 32767 |
signed (two's complement) | -32768 to 32767 | |||
unsigned | 0 to 6.55 · 104 | 0 to 65535 | ||
32 | signed (one's complement) | ± 2.14 · 109 | -2,147,483,647 to 2,147,483,647 | |
signed (two's complement) | -2,147,483,648 to 2,147,483,647 | |||
unsigned | 0 to 4.29 · 109 | 0 to 4,294,967,295 | ||
64 | signed (one's complement) | ± 9.22 · 1018 | -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807 | |
signed (two's complement) | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | |||
unsigned | 0 to 1.84 · 1019 | 0 to 18,446,744,073,709,551,615 | ||
floating point | 32 | IEEE-754 |
|
|
64 | IEEE-754 |
|
|
Note: actual (as opposed to guaranteed minimal) ranges are available in the library headers <limits.h> and <float.h>
See also
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/c/language/arithmetic_types