Data type
Every kind of data in C has a type, and the compiler must know the type of the data in order to manipulate it. A 'type' is a common characteristic shared by similar data, so once the data type of a value is known, it is possible to know the characteristics of that value and how to manipulate it.
There are three basic data types: character (char), integer (int) and float (float). Complex types are constructed on the basis of them.
Character types
A character type refers to a single character and the type declaration uses the char
keyword.
char c = 'B';
The above example declares the variable c
as a character type and assigns it to the letter B
.
The C language specifies that character constants must be placed inside single inverted commas.
Internally, character types are stored using one byte (8 bits). c treats them as integers, so a character type is an integer of one byte in width. Each character corresponds to an integer (determined by the ASCII code), for example B
corresponds to the integer 66
.
The default range of character types varies from computer to computer. Some systems default to -128
to 127
, others default to 0
to 255
. Both of these ranges happen to cover the ASCII character range of 0
to 127
.
Integers and characters are interchangeable and can be assigned to variables of character type as long as they are within the range of the character type.
char c = 66;
// Equivalent to
char c = 'B';
In the above example, the variable c
is a character type and the value assigned to it is the integer 66. This has the same effect as assigning the value to the character B
.
Two variables of type character can perform mathematical operations.
char a = 'B'; // equivalent to char a = 66;
char b = 'C'; // equivalent to char b = 67;
printf("%d\n", a + b); // output 133
In the above example, the character type variables a
and b
are added together as if they were two integers. The placeholder %d
means that the output is a decimal integer, so the output is 133.
The single inverted comma is itself a character, and to represent this character constant, a backslash escape must be used.
char t = '\'';
In the above example, the variable t
is a single quote character, and since the character constant must be placed inside a single quote, the internal single quote is to be escaped using a backslash.
This escape is written mainly to represent some unprintable control characters defined in ASCII code, which are also values of character type.
\a
: an alert, which causes the terminal to sound an alarm or to blink, or both.\b
: backspace, the cursor goes back one character but does not delete the character.\f
: the page break character, which moves the cursor to the next page. On modern systems this is no longer reflected, and the behaviour is changed to something like\v
.\n
: the line feed character.\r
: the carriage return character, where the cursor moves to the beginning of the same line.\t
: tab character, the cursor moves to the next horizontal tab position, usually the next multiple of 8.\v
: vertical separator, the cursor moves to the next vertical tab, usually the same column of the next line.\0
: the null character, representing no content. Note that this value is not equal to the number 0.
Escape writing can also represent a character using octal and hexadecimal.
\nn
: octal writing of the character, withnn
being the octal value.\xnn
: hexadecimal writing of the character, withnn
being the hexadecimal value.
char x = 'B';
char x = 66;
char x = '\102'; // octal
char x = '\x42'; // hexadecimal
The four ways of writing the above example are all equivalent.
Integer types
Introduction
The integer type is used to represent larger integers. The type declaration uses the `int
'' keyword.
int a;
The above example declares an integer variable a
.
The size of the int
type varies from computer to computer. It is more common to use 4 bytes (32 bits) to store a value of type int
, but it is possible to use 2 bytes (16 bits) or 8 bytes (64 bits). The range of integers they can represent is as follows.
- 16-bit: -32,768 to 32,767.
- 32-bit: -2,147,483,648 to 2,147,483,647.
- 64 bits: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
signed, unsigned
C uses the signed
keyword to indicate that a type has a positive or negative sign and contains negative values, and the unsigned
keyword to indicate that the type does not have a positive or negative sign and can only represent zero and positive integers.
For the int
type, the default is to have a positive or negative sign, meaning that int
is equivalent to signed int
. Since this is the default, the keyword signed
is usually omitted, but it is not wrong to write it.
signed int a;
// is equivalent to
int a;
The int
type can also be used without a plus or minus sign, to represent only non-negative integers. In this case the variable must be declared using the keyword unsigned
.
unsigned int a;
The advantage of declaring an integer variable as unsigned
is that the maximum integer value that can be represented by the same length of memory is doubled. For example, the maximum value of a 16-bit signed int
is 32,767, while the maximum value of an unsigned int
is increased to 65,535.
The int
inside unsigned int
can be omitted, so the variable declaration above can also be written as follows.
unsigned a;
The character type char
can also be set to signed
and unsigned
.
signed char c; // range is -128 to 127
unsigned char c; // range is 0 to 255
Note that the C language specifies that the char
type has a positive or negative sign by default, as determined by the current system. This means that char
is not equivalent to signed char
, it may be either signed char
or unsigned char
. This is different from int
, which is the equivalent of signed int
.
Subtypes of integers
If the int
type uses 4 or 8 bytes to represent an integer, this is a waste of space for small integers. On the other hand, there are occasions when larger integers are needed and 8 bytes are not enough. To solve these problems, C provides three subtypes of integers in addition to the int
type. This facilitates finer scoping of integer variables and a better expression of the code's intent.
short int
(abbreviated asshort
): takes up no more space thanint
, usually 2 bytes (integers range from -32768 to 32767).long int
(abbreviated aslong
): takes up no less thanint
space and at least 4 bytes.long long int
(abbreviated aslong long
): takes up more space thanlong
and is at least 8 bytes.
short int a;
long int b;
long long int c;
The above code declares variables of each of the three integer subtypes.
By default, short
, long
and long long
are all signed (signed), i.e. the signed
keyword is omitted. They can also be declared unsigned, which doubles the maximum value that can be represented.
unsigned short int a;
unsigned long int b;
unsigned long long int c;
C allows int
to be omitted, so variable declaration statements can also be written as follows.
short a;
unsigned short a;
long b;
unsigned long b; unsigned long b;
long long c;
unsigned long long c;
The byte length of data types varies from computer to computer. When you really need a 32-bit integer, you should use the long
type instead of the int
type, which ensures that it is no less than 4 bytes; when you really need a 64-bit integer, you should use the long long
type, which ensures that it is no less than 8 bytes. On the other hand, to save space, the short
type should be used when only 16-bit integers are needed; when 8-bit integers are needed, the char
type should be used.
Limiting values for integer types
Sometimes it is necessary to check the maximum and minimum values of different integer types on the current system. The C header file limits.h
provides the appropriate constants, for example SCHAR_MIN
for the minimum value of -128
for the signed char type and SCHAR_MAX
for the maximum value of 127
for the signed char type.
For code portability, these constants should be used as much as possible when the limits of an integer type need to be known.
SCHAR_MIN
,SCHAR_MAX
: the minimum and maximum values of signed char.SHRT_MIN
,SHRT_MAX
: the minimum and maximum values of short.INT_MIN
,INT_MAX
: the minimum and maximum values of int.LONG_MIN
,LONG_MAX
: minimum and maximum values of long.LLONG_MIN
,LLONG_MAX
: the minimum and maximum values of long long.UCHAR_MAX
: The maximum value of unsigned char.USHRT_MAX
: the maximum value of unsigned short.UINT_MAX
: the maximum value of unsigned int.ULONG_MAX
: maximum value of unsigned long.ULLONG_MAX
: the maximum value of unsigned long long.
Integer binary
C integers are all decimal numbers by default; to represent octal and hexadecimal numbers, you must use a special representation.
Octal uses 0
as a prefix, e.g. 017
, 0377
.
int a = 012; // octal, equivalent to 10 in decimal
十六进制使用0x
或0X
作为前缀,比如0xf
、0X10
。
int a = 0x1A2B; // 十六进制,相当于十进制的6699
有些编译器使用0b
前缀,表示二进制数,但不是标准。
int x = 0b101010;
Note that the different binary is just the way the integer is written, and has no effect on how the integer is actually stored. All integers are stored in binary form, independent of the way they are written. The different bases can be mixed, for example 10 + 015 + 0x20
is a legal expression.
The binary-related placeholders for printf()
are as follows.
%d
: decimal integer.%o
: octal integer.%x
: hexadecimal integer.%#o
: displays octal integers prefixed with0
.%#x
: display of hexadecimal integers prefixed with0x
.%#X
: displays the hexadecimal integers prefixed with0X
.
int x = 100;
printf("dec = %d\n", x); // 100
printf("octal = %o\n", x); // 144
printf("hex = %x\n", x); // 64
printf("octal = %#o\n", x); // 0144
printf("hex = %#x\n", x); // 0x64
printf("hex = %#X\n", x); // 0X64
Floating point types
任何有小数点的数值,都会被编译器解释为浮点数。 所谓“浮点数”就是使用 m * be 的形式,存储一个数值,m
是小数部分,b
是基数(通常是2
),e
是指数部分。 这种形式是精度和数值范围的一种结合,可以表示非常大或者非常小的数。
浮点数的类型声明使用float
关键字,可以用来声明浮点数变量。
float c = 10.5;
上面示例中,变量c
的就是浮点数类型。
float
类型占用4个字节(32位),其中8位存放指数的值和符号,剩下24位存放小数的值和符号。 float
类型至少能够提供(十进制的)6位有效数字,指数部分的范围为(十进制的)-37
到37
,即数值范围为10-37到1037。
有时候,32位浮点数提供的精度或者数值范围还不够,C 语言又提供了另外两种更大的浮点数类型。
double
:占用8个字节(64位),至少提供13位有效数字。long double
:通常占用16个字节。
注意,由于存在精度限制,浮点数只是一个近似值,它的计算是不精确的,比如 C 语言里面0.1 + 0.2
并不等于0.3
,而是有一个很小的误差。
if (0.1 + 0.2 == 0.3) // false
C 语言允许使用科学计数法表示浮点数,使用字母e
来分隔小数部分和指数部分。
double x = 123.456e+3; // 123.456 x 10^3
// 等同于
double x = 123.456e3;
上面示例中,e
后面如果是加号+
,加号可以省略。 注意,科学计数法里面e
的前后,不能存在空格。
另外,科学计数法的小数部分如果是0.x
或x.0
的形式,那么0
可以省略。
0.3E6
// 等同于
.3E6
3.0E6
// 等同于
3.E6
布尔类型
C 语言原来并没有为布尔值单独设置一个类型,而是使用整数0
表示伪,所有非零值表示真。
int x = 1;
if (x) {
printf("x is true!\n");
}
In the above example, the variable x
is equal to 1
, and C assumes that this value represents true, and thus executes the code inside the judgment body.
The C99 standard adds the type _Bool
, which represents a boolean value. However, this type is really just an alias for the integer type, and still uses 0
for pseudo and 1
for true, as shown in the following example.
_Bool isNormal;
isNormal = 1;
if (isNormal)
printf("Everything is OK.\n");
The header file stdbool.h
defines another type alias bool
, and defines true
for 1
and false
for 0
. As soon as this header file is loaded, these keywords can be used.
#include <stdbool.h>
bool flag = false;
In the example above, once the header file stdbool.h
is loaded, you can use bool
to define the boolean type, and false
and true
to indicate true or false.
Types of literals
A literal is a value that appears directly inside the code.
int x = 123;
In the above code, x
is the variable and 123
is the literal.
When compiling, the literal is also written to memory, so the compiler must specify the data type for the literal, just as it must specify the data type for the variable.
Normally, a decimal integer literal (e.g. 123
) will be specified by the compiler as type int
. If a value is larger than int
can represent, the compiler will specify it as long int
. If the value exceeds long int
, it will be specified as unsigned long
. If it is not large enough, it is specified as long long
or unsigned long long
.
Fractional numbers (e.g. 3.14
) are specified as double
types.
Literal suffixes
Sometimes a programmer wishes to specify a different type for a literal quantity. For example, if the compiler specifies an integer literal as type int
, but the programmer wishes to specify it as type long
, the literal can be suffixed with l
or L
and the compiler will know to specify the type of the literal as long
.
int x = 123L;
In the code above, the literal 123
has the suffix L
, and the compiler will then specify it as type long
. Here 123L
is written as 123l
, which has the same effect, but it is recommended that L
be used in preference, as the lower case l
is easily confused with the number 1
.
Octal and hexadecimal values can also be specified as Long types using the suffixes l
and L
, for example 020L
and 0x20L
.
int y = 0377L;
int z = 0x7fffL;
If you wish to specify as unsigned integer unsigned int
, you can use the suffix u
or U
.
int x = 123U;
L
and U
can be used in combination to indicate the type unsigned long
. The case and order of combination of L
and U
does not matter.
int x = 123LU;
For floating point numbers, the compiler specifies the type double by default; if you wish to specify another type, you need to add the suffix f
(float) or l
(long double) to the decimal.
Scientific notation can also use the suffix.
1.2345e+10F
1.2345e+10L
To summarise, the following literal quantity suffixes are commonly used.
f` and
F: ``float
types.l
andL
: the typelong int
for integers andlong double
for decimals.ll
andLL
: Long Long types, e.g.3LL
.u
andU
: representunsigned int
, e.g.15U
,0377U
.
u
can also be combined with other integer suffixes, either in front or after, e.g. 10UL
, 10ULL
and 10LLU
are all legal.
Here are some examples.
int x = 1234;
long int x = 1234L;
long long int x = 1234LL
unsigned int x = 1234U;
unsigned long int x = 1234UL;
unsigned long long int x = 1234ULL;
float x = 3.14f;
double x = 3.14;
long double x = 3.14L;
Overflow
Each data type has a range of values. If a value is stored outside this range (less than the minimum or greater than the maximum) and more binary bits are needed to store it, an overflow will occur. A value greater than the maximum is called an overflow; a value less than the minimum is called an underflow.
Generally speaking, the compiler will not report an overflow and will execute the code normally, but will ignore the extra binary bits and only keep the remaining bits, which can often lead to unexpected results. So, overflows should be avoided.
unsigned char x = 255;
x = x + 1;
printf("%d\n", x); // 0
In the example above, adding 1
to the variable x
gives a result of not 256
but 0
. Because x
is of type unsign char
and has a maximum value of 255
(binary 11111111
), adding 1
causes an overflow to occur and the highest bit 1
of 256
(binary 100000000
) is discarded, leaving the value 0
.
Look again at the following example.
unsigned int ui = UINT_MAX; // 4,294,967,295
ui++;
printf("ui = %u\n", ui); // 0
ui--;
printf("ui = %u\n", ui); // 4,294,967,295
In the above example, the constant UINT_MAX
is the maximum value of the unsigned int type. If 1
is added, it overflows for that type, giving 0
; and 0
is the minimum value for that type, which is then subtracted from 1
to give UINT_MAX
again.
The overflow is easy to ignore and the compiler does not report an error, so great care must be taken.
for (unsigned int i = n; i >= 0; --i) // error
The above code seems fine on the surface, but the loop variable i
is of type unsigned int, the smallest value of this type is 0
and it is impossible to get a result less than 0. When i
equals 0 and 1
is subtracted, it does not return -1
, but the maximum value of the type unsigned int, which is always greater than or equal to 0
, leading to an infinite loop.
To avoid overflow, the best way is to compare the result of the operation with the type's limit.
unsigned int ui;
unsigned int sum;
// Error
if (sum + ui > UINT_MAX) too_big();
else sum = sum + ui;
// correct
if (ui > UINT_MAX - sum) too_big();
else sum = sum + ui;
In the above example, the variables sum
and ui
are both of type unsigned int, and the sum of them is still of type unsigned int, which makes it possible for an overflow to occur. However, you cannot tell if an overflow has occurred by whether the sum exceeds the maximum value UINT_MAX
, because sum + ui
always returns the result of the overflow and cannot be greater than UINT_MAX
. The correct way to compare is to determine the magnitude of the relationship between UINT_MAX - sum
and ui
.
Here is another incorrect way to write it.
unsigned int i = 5;
unsigned int j = 7;
if (i - j < 0) // error
printf("negative\n");
else
printf("positive\n");
The result of the above example will output positive
. The reason for this is that the variables i
and j
are of type unsigned int, and the result of i - j
is also of this type, with a minimum value of 0
, so it is impossible to get a result less than 0
. The correct way to write this is as follows.
if (j > i) // ....
sizeof operator
sizeof
is an operator provided by the C language that returns the number of bytes occupied by a certain data type or a value. Its argument can be a keyword of a data type, a variable name or a specific value.
// The argument is a data type
int x = sizeof(int);
// the argument is a variable
int i;
sizeof(i);
// parameter is a numeric value
sizeof(3.14);
The first example above returns the number of bytes occupied by the int
type (usually 4
or 8
). The second example returns the number of bytes occupied by an integer variable, with exactly the same result as the previous example. The third example returns the number of bytes occupied by the floating point number 3.14
, and since floating point literals are always stored as double types, 8
is returned because of the 8 bytes occupied by the double type.
The return value of the sizeof
operator is only specified in C as an unsigned integer, not a specific type, leaving it up to the system to decide exactly what type sizeof
will return. Depending on the system, the return value may be of type unsigned int
, unsigned long
, or even unsigned long long
, with the corresponding printf()
placeholders being %u
, %lu
and %llu
respectively. This is not conducive to program portability.
The C language provides a solution by creating a type alias size_t
to unify the return value type of sizeof
. This alias is defined in the stddef.h
header file (which is automatically introduced when stdio.h
is introduced) and corresponds to the current system return type of sizeof
, which may be unsigned int
or unsigned long
.
The C language also provides a constant SIZE_MAX
which indicates the maximum integer that size_t
can represent. So, the range of integers that size_t
can represent is [0, SIZE_MAX]
.
printf()
has a special placeholder %zd
or %zu
for values of type size_t
.
printf("%zd\n", sizeof(int));
The %zd
placeholder (or %zu
) is output correctly in the above code, regardless of the type of the sizeof
return value.
If the current system does not support %zd
or %zu
, %u
(unsigned int) or %lu
(unsigned long int) can be used instead.
Automatic conversion of types
In some cases, C will automatically convert the type of a value.
Assignment operations
The assignment operator automatically converts the value on the right to the type of the variable on the left.
(1) Assigning floating-point numbers to integer variables
When assigning a floating point number to an integer variable, C discards the decimal part directly, rather than rounding.
int x = 3.14;
In the above example, the variable x
is an integer type and the value assigned to it is a floating point number. The compiler will automatically convert 3.14
to an int
type first, discard the fractional part, and then assign the value to x
, so the value of x
is 3
.
This automatic conversion causes some of the data to be lost (3.14
loses the fractional part), so it is best not to assign values across types and try to ensure that the variable is of the same type as the value to be assigned.
Note that when rounding off the decimal part, it is not rounded off, but the whole thing is rounded off.
int x = 12.99;
In the example above, x
is equal to 12
, not 13
which is rounded off.
(2) Assigning integers to floating-point variables
When an integer is assigned to a floating point variable, it will automatically be converted to a floating point number.
float y = 12 * 2;
In the above example, the value of the variable y
is not 24
but 24.0
because the integer to the right of the equal sign is automatically converted to a floating point number.
(3) assignment of narrow types to wide types
When an integer type with a small byte width is assigned to an integer variable with a large byte width, type boosting occurs, i.e. the narrow type is automatically converted to a wide type.
For example, an assignment of a char
or short
type to an int
type will automatically be promoted to int
.
char x = 10;
int i = x + y;
In the above example, the variable x
is of type char
and will be automatically raised to int
because of the assignment to type int
.
(4) Assignment of wide types to narrow types
When a type with a larger byte width is assigned to a variable with a smaller byte width, a type degradation occurs and it is automatically converted to the latter type. This may result in truncation, where the system automatically truncates the extra binary bits, leading to unpredictable results.
int i = 321;
char ch = i; // the value of ch is 65 (321 - 256)
In the above example, the variable ch
is of type char
and has a width of 8 binary bits. The variable i
is of type int
and assigns i
to ch
, which can only hold the last eight bits of i
(in binary form as 101000001
, 9 bits in total), the extra binary bits before that are discarded and the last eight bits are retained to make 01000001
(65 in decimal, equivalent to the character A
).
Truncation also occurs when a floating point number is assigned to an integer type value, and the fractional part of the floating point number is truncated.
double pi = 3.14159;
int i = pi; // the value of i is 3
In the example above, i
is equal to 3
and the fractional part of pi
is truncated.
Mixed type arithmetic
When values of different types are mixed, they must first be converted to the same type before they can be calculated. The rules for conversion are as follows.
(1) When mixing integers and floating point numbers, the integer is converted to a floating point type of the same type as the other operator.
3 + 1.2 // 4.2
The above example is a mixture of int
type and float
type. 3
of int
type will first be converted to 3.0
of float
, and then calculated to get 4.2
.
(2) When different floating point types are mixed, the type with smaller width is converted to the type with larger width, e.g. float
to double
and double
to long double
.
(3) When different integer types are mixed, the type with the smaller width will be raised to the type with the larger width. For example, short
to int
, int
to long
, etc. Sometimes the signed type signed
is also converted to unsigned unsigned
.
The following example is executed with results that may be surprising.
int a = -5;
if (a < sizeof(int))
do_something();
In the example above, the variable a
is a signed integer and sizeof(int)
is of type size_t
, which is an unsigned integer. According to the rules, signed int is automatically converted to unsigned int, so a
will automatically be converted to unsigned integer 4294967291
(the conversion rule is -5
plus the maximum value of the unsigned integer, plus 1), causing the comparison to fail and do_something()
will not be executed.
Therefore, it is best to avoid mixing unsigned integers with signed integers. This is because the C language will then automatically convert signed int
to unsigned int
and may not give the expected result.
Arithmetic on integer types
When two integers of the same type are operated on, or when a single integer is operated on, the result is generally of the same type. There is one exception, however, where the result of an operation on a type of width less than int
is automatically raised to int
.
unsigned char a = 66;
if ((-a) < 0) printf("negative\n");
else printf("positive\n");
In the above example, the variable a
is of type unsigned char, which cannot be less than 0. However, -a
is not of type unsigned char and will automatically be converted to int, resulting in the above code outputting negative.
Look at the following example again.
unsigned char a = 1;
unsigned char b = 255;
unsigned char c = 255;
if ((a - 5) < 0) do_something();
if ((b + c) > 300) do_something();
In the above example, the expressions a - 5
and b + c
are both automatically converted to int types, so the function do_something()
will be executed twice.
Functions
The arguments and return values of a function are automatically converted to the type specified in the function definition.
int dostuff(int, unsigned char);
char m = 42;
unsigned short n = 43;
long long int c = dostuff(m, n);
In the above example, the argument variables m
and n
are converted to the type of the argument defined by the function dostuff()
, regardless of their original type.
The following is an example of automatic type conversion of the return value.
char func(void) {
int a = 42;
return a;
}
In the above example, the variable a
inside the function is of type int
, but the value returned is of type char
, because that is the type returned in the function definition.
Explicit conversion of types
In principle, automatic conversion of types should be avoided to prevent unexpected results. the C language provides explicit conversion of types, allowing manual conversion of types.
A value or variable can be converted to the specified type by specifying the type (type)
in parentheses in front of the value or variable, this is called "type casting".
(unsigned char) ch
The above example casts the variable ch
into an unsigned character type.
long int y = (long int) 10 + 12;
In the above example, (long int)
converts 10
explicitly to the type long int
. The display conversion here is actually unnecessary, as the assignment operator automatically converts the value on the right, to the type of the variable on the left.
Portable types
The C integer types (short, int, long) may take up different byte widths on different computers, and it is impossible to know in advance exactly how many bytes they will take up.
Programmers sometimes control the exact byte width so that the code can have better portability, and the header file stdint.h
has created some new type aliases.
(1) exact-width integer type, which guarantees that the width of a given integer type is deterministic.
int8_t
: 8-bit signed integers.int16_t
: 16-bit signed integer.int32_t
: 32-bit signed integer.int64_t
: 64-bit signed integer.uint8_t
: 8-bit unsigned integer.uint16_t
: 16-bit unsigned integer.uint32_t
: 32-bit unsigned integer.uint64_t
: 64-bit unsigned integer.
All of the above are type aliases, and the compiler will specify the underlying type they point to. For example, on a given system, if int
is of type 32 bits, int32_t
will point to int
; if long
is of type 32 bits, int32_t
will point to long
.
Here is an example of its use.
#include <stdio.h>
#include <stdint.h>
int main(void) {
int32_t x32 = 45933945;
printf("x32 = %d\n", x32);
return 0;
}
In the above example, the variable x32
is declared as type int32_t
, which is guaranteed to be 32 bits wide.
(2) The minimum width type, which guarantees the minimum length of an integer type.
- int_least8_t
- int_least16_t
- int_least32_t
- int_least64_t
- uint_least8_t
- uint_least16_t
- uint_least32_t
- uint_least64_t
These types above are guaranteed to occupy no less than the specified width of bytes. For example, int_least8_t
indicates the minimum width type that can hold an 8-bit signed integer.
(3) Fast minimum width type, the type that allows the fastest integer calculation.
- int_fast8_t
- int_fast16_t
- int_fast32_t
- int_fast64_t
- uint_fast8_t
- uint_fast16_t
- uint_fast32_t
- uint_fast64_t
The above types are designed to guarantee byte width while seeking the fastest possible operation, for example int_fast8_t
indicates the fastest type for 8-bit signed integers. This is because some machines operate fastest on data of a particular width, for example, a 32-bit computer will operate faster on 32-bit data than on 16-bit data.
(4) The type of integer that can hold a pointer.
intptr_t
: signed integer type that can store a pointer (memory address).uintptr_t
: unsigned integer type that can store a pointer.
(5) Maximum width integer type for storing the largest integer.
intmax_t
: type that can store any valid signed integer.uintmax_t
: can store any valid unsigned integer type.
These two types above are wider than long long
and unsigned long
.