Primitive Types
Primitive types (or fundamental types) are built-in types that are part of the core language, and almost always available to you.
These types will work on any platform, but their features (e.g. size and memory layout) may differ depending on the infrastructure.
"F.S."
Each type has their own printf() format specifier, which I will abbreviate "F.S."
You will normally use this format specifier to print a variable/expression of that type using printf().
Integer types
These store integers (whole numbers).
Types of integer types
There are four sizes:
short(2 bytes),int(4 bytes),long(4 or 8 bytes), andlong long(8 bytes).- Thanks to the specification,
longcan be 4 bytes or 8 bytes. (It's 8 bytes on 64-bit Linux or Mac; 4 bytes elsewhere.)
- Thanks to the specification,
Each integer type can be signed (e.g.
int) or unsigned (e.g.unsigned int)- If signed, it can store negative, zero, and positive values
- If unsiged, it can store zero and positive values only
| Type | Size | Min value | Max value | F.S. |
|---|---|---|---|---|
short | 2 bytes | −32,768 | 32,767 | %hd |
unsigned short | 2 bytes | 0 | 65,535 | %hu |
int | 4 bytes | ≈ (−2.14)×109 | ≈ 2.14×109 | %d |
unsigned int | 4 bytes | 0 | ≈ 4.29×109 | %u |
long | 4 or 8 bytes | — | — | %ld |
unsigned long | 4 or 8 bytes | — | — | %lu |
long long | 8 bytes | ≈ (−9.22)×1018 | ≈ 9.22×1018 | %lld |
unsigned long long | 8 bytes | 0 | ≈ 18.44×1018 | %llu |
Integer literals
When we say literal, it means hardcoded values in your program.
- To write in decimal — just write the number normally, e.g.
1234or-1234 - To write in ocatal (base 8) — prefix the number with
0, e.g.067or-067 - To write in binary (base 2) — prefix the number with
0b, e.g.0b0011or-0b0011 - To write in hexadecimal (base 16) — prefix the number with
0x, e.g.0x9abor-0x9ab
When you write an integer literal, the compiler will assume its type as either int, long, or long long (it will pick the smallest one that fits). If you want more control, you can narrow down its type by suffixing it with any of these (they are case insensitive).
lorL— to make it a SIGNEDlong(orlong long)llorLL— to make it a SIGNEDlong longuorU— to make it anunsigned int(orunsigned longorunsigned long long)ulorUL— to make it anunsigned long(orunsigned long long)ullorULL— to make it anunsigned long long
Formatting integers
%o— format-print an integer type in its octal representation%x— format-print an integer type in its hexademical representation
int number = 123;
printf("%d in HEX is %x!\n", number, number);
//=> 123 in HEX is 7b!
Floating-point types
These store approximations of real numbers. (Because the space to store the numbers are limited, there could be precision errors when representing real numbers.)
Types of floating-point types
long double is usually the same as double (just use double).
| Type | Size | Min value | Max value | F.S. |
|---|---|---|---|---|
float | 4 bytes | ≈ (−3.40)×1038 | ≈ 3.40×1038 | %f |
double | 8 bytes | ≈ (−1.79)×10308 | ≈ 1.79×10308 | %lf |
long double | 8 bytes | ≈ (−1.79)×10308 | ≈ 1.79×10308 | %Lf |
Floating-point literals
There are two ways to write a floating-point literal:
- Write it normally — e.g.
123.45,-123.45,456(integer literals are valid, too) - Write it in scientific notation — e.g.
1.9e2(1.9×102) or-2.1e-2(−2.1×10-2)
When you write a floating-point literal, the compiler will assume its type as double by default. If you want more control, you can specify its type by suffixing it with any of these (they are case insensitive).
forF— to make it afloat, e.g.2.7florL— to make it along double, e.g.4.8L
Formatting floating-point numbers
%g to print floating-point numbers.%f,%lf, or%Lf— print normally (with trailing zeroes), e.g.54321.000000or9.750000%e— format-print the number in scientific notation, e.g.6.02214e+23or9.750000e+00%g— choose the shortest representation between%f(or%lf) and%e, removing the trailing zeroes, e.g.6.02214e+23or9.75
You can further format your number with additional flags/arguments in your printf format specifier. For example, printing 1.2555 with %+08.2lf will give you +0001.26:
- the
+prefix flag — means always print the sign, i.e.+or- - the
0prefix flag — means left-pad the number with zeroes - the
8width argument — means the formatted number will take at least 8 characters - the
.2precision argument — means always display 2 digits after the decimal point (the default is 6)
Character types
These store a single human language character, e.g. "A".
Types of character types
- "Narrow characters":
char— May be signed or unsigned (depending on the compiler). It can store an ASCII character or a 1-byte integer.
- "Wide characters" (because they can store more than 1 byte):
char16_t— It can store a 2-byte character set, e.g. an UTF-16 character.char32_t— It can store a 4-byte character set, e.g. an UTF-32 character.wchar_t— May be 2 bytes or 4 bytes (depending on the compiler). It can store, for example, Unicode characters (2 bytes).
| Type | Size | Min value | Max value | F.S. |
|---|---|---|---|---|
char | 1 byte | — | — | %c |
signed char | 1 byte | -128 | 127 | %c |
unsigned char | 1 byte | 0 | 255 | %c |
char16_t | 2 bytes | 0 | 65,535 | * |
char32_t | 4 bytes | 0 | ≈ 4.29×109 | * |
wchar_t | 2 or 4 bytes | — | — | %lc |
(*) char16_t and char32_t don't exactly have a format specifier (you will need to convert them first if you want to print them). Alternatively, you can use %#x to print the character using their hexadecimal representation, e.g. 0x6c34 for 水 (The # flag adds the 0x prefix).
Character literals
Quote them using single quotes ('), e.g. 'x'.
If the type is not char, you must also give the following prefix:
u— to make itchar16_t, e.g.u'x'U— to make itchar32_t, e.g.U'x'L— to make itwchar_t, e.g.L'x'
Character escapes
To enter special characters:
\r— to enter the carriage return character\n— to enter the newline character\t— to enter the tab character\0— to enter the null character\'— to enter the'character\"— to enter the"character\\— to enter the\character\0— to enter the null character
To enter Unicode characters:
\uXXXX(4-digit Unicode code point) — e.g.\u0041to enterA\UXXXXXXXX(8-digit Unicode code point) — e.g.\U0001F37Ato enter🍺
Boolean types
These store true or false.
Types of boolean types
There is only a single boolean type: bool.
(Note that even though technically it only requires a single bit to store a true/false value, bool requires 1 byte.)
| Type | Size | Min value | Max value | F.S. |
|---|---|---|---|---|
bool | 1 byte | 0 | 1 | ** |
(**) There are no format specifier for the bool type. Instead, you can use %d to print it as 0 oir 1.
Boolean literals
Just write true or false.
Additionaly, the following shows the equivalence between boolean and integer types:
trueis equivalent to1falseis equivalent to0- Any non-zero integer value is equivalent to
true - Zero is equivalent to
false
Void types
The void type stores no value.
In fact, you cannot define a variable with a void type. You use void in "special situations," for example, to denote the return type of a function that doesn't return anything.
void greet() {
printf("Hello!\n");
}
Other notable types
std::byte
Defined in <cstddef> (#include <cstddef>), this type is usually used to handle raw memory (collection of bits without a type).
size_t
Defined in <cstddef> (#include <cstddef>), this type represents the size of an object in bytes. (Its actual type depends on the compiler, but you can think of it as an unsigned integer, usually unsigned long long.)
When you use the typeof operator, e.g. sizeof(double), the return type would be size_t. Its format specifier is %zu.
size_t size_double = sizeof(double);
printf("%zu\n", size_double);
//=> 8 (because double type requires 8 bytes)
References
- C++ Crash Course (Josh Lospinoso) — 2. Types
- Why are C++ int and long types both 4 bytes? — https://stackoverflow.com/questions/13398630/why-are-c-int-and-long-types-both-4-bytes
- C and C++ Integer Limits — https://docs.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=msvc-170
- Type float — https://docs.microsoft.com/en-us/cpp/c-language/type-float?view=msvc-170
- printf — https://www.cplusplus.com/reference/cstdio/printf/
- char16_t — https://en.cppreference.com/w/c/string/multibyte/char16_t
- char32_t — https://en.cppreference.com/w/c/string/multibyte/char32_t
- size_t — https://en.cppreference.com/w/c/types/size_t