Modern C++
Programming
3. Basic Concepts I
Type System, Fundamental Types, and Operators
Federico Busato
2026-01-06
Table of Contents
1 The C++ Type System
Type Categories
Type Properties
⋆
2 Fundamental Types Overview
Arithmetic Types
Non-Standard Arithmetic Types
void Type
nullptr
1/22
Table of Contents
3 auto Keyword
4 C++ Operators
Operators Precedence
Prefix/Postfix Increment/Decrement Semantic
Assignment, Compound, and Comma Operators
Spaceship Operator <=>
⋆
2/22
The C++ Type
System
The C++ Type System
C++ is a strongly typed and statically typed language
Every entity has a type and that type never changes
Every variable, function, or expression has a type in order to be compiled. Users can
introduce new types with class or struct
The type specifies:
• The amount of memory allocated for the variable (or expression result)
• The kinds of values that may be stored and how the compiler interprets the bit
patterns in those values
• The operations that are permitted for those entities and provides semantics
3/22
Type Categories
C++ organizes the language types in two main categories:
• Fundamental types: often called primitive types, or less precisily builtin types.
Types provided by the language itself that don’t require additional headers
• Arithmetic types: integer and floating point
• void
• nullptr_t C++11
• Compound types: Composition or references to other types
• Pointers
• References
• Enumerators
• Arrays
• struct , class , union
• Functions
4/22
Type Properties
⋆
1/2
C++ types can be also classified based on their properties:
• Trivial types: Trivial default/copy constructor, copy assignment operator, and
destructor → Trivially Copyable
examples: Scalar, trivial class types, arrays of such types
• Scalar:
• Hold a single value and is not composed of other objects
• Trivially Copyable: can be copied bit for bit
• Standard Layout: compatible with C functions and structs
• Implicit Lifetime: no user-provided constructor or destructor
examples: Arithmetic, Pointers and nullptr , Enumerators
5/22
Type Properties
⋆
2/2
• Objects:
• size: sizeof is defined
• alignment requirement: alignof is defined
• storage duration: describe when an object is allocated and deallocated
• lifetime, bounded by storage duration or temporary
• value, potentially indeterminate
• optionally, a name.
examples: Arithmetic, Pointers and nullptr , Enumerators, Arrays, struct , class ,
union
• Incomplete types: A type that has been declared but not yet defined
examples: void , incompletely-defined object types, e.g. struct A; , array of elements
of incomplete type
6/22
C++ Types Summary
7/22
Fundamental Types
Overview
Arithmetic Types
Type Bytes
bool 1
char
†$
1
unsigned char 1
short
$
2
unsigned short 2
int
$
4
unsigned 4
long
$
4
∗
/8
long unsigned 4
∗
/8
long long
$
8
long long unsigned 8
Standard Type Bytes
C++23 (bfloat16) 2
C++23 (float16) 2
float 4
double 8
C++23 (float128) 16
∗
on Windows 64-bit
8/22
Non-Standard Arithmetic Types
• C++ also provides long double (no IEEE-754) of size 8/12/16 bytes
depending on the implementation
• Reduced precision floating-point supports before C++23:
- Some compilers provide support for half (16-bit floating-point) (GCC for ARM:
__fp16 ,
LLVM compiler: half )
- Some modern CPUs and GPUs provide half instructions
- Software support: OpenGL, Photoshop, Lightroom, half.sourceforge.net
• C++ does not provide 128-bit integers even if some architectures support it.
clang and gcc allow 128-bit integers as compiler extension ( __int128 )
9/22
void Type
void is an incomplete type (not defined) without a value
• void indicates also a function with no return type or no parameters
e.g. void f() , f(void)
• In C sizeof(void) == 1 (GCC), while in C++ sizeof(void) does not
compile!!
int main() {
// sizeof(void); // compile error
}
10/22
nullptr Keyword
C++11 introduces the keyword nullptr to represent a null pointer ( 0x0 ) and
replacing the NULL macro
nullptr is an object of type nullptr_t → safer
int* p1 = NULL; // ok, equal to int* p1 = 0l
int* p2 = nullptr; // ok, nullptr is convertible to a pointer
int n1 = NULL; // ok, we are assigning 0 to n1
//int n2 = nullptr; // compile error nullptr is not convertible to an integer
//int* p2 = true ? 0 : nullptr; // compile error incompatible types
11/22
auto Keyword
auto Keyword 1/4
C++11 The auto keyword specifies that the type of the variable will be automatically
deduced by the compiler from its initializer expression
auto a = 1 + 2; // 'a' is "int"
auto b = 2.0; // 'b' is double
12/22
auto Keyword
⋆
2/4
auto can be very useful for maintainability and for hiding complex type definitions
// 'i' has the same type of 'k'
for (auto i = k; i < size; i++)
...
std::vector<int> x{1, 2, 3};
std::vector<int>::iterator i1 = x.begin();
auto i2 = x.begin();
On the other hand, it may make the code less readable or even bug-prone if excessively
used because of type hiding
Example: auto x = 0; is less readable than int x = 0
13/22
auto Keyword - Function Return Type
⋆
3/4
In C++14, auto (as well as decltype ) can be used to define function output types
(aka trailing return type)
auto h(int x) { return x * 2; }
In C++11, the return type needs to be explicitly specified:
auto g(int x) -> int { return x * 2; } // C++11
// "-> int" is the deduction type
// a better way to express it is:
auto g2(int x) -> decltype(x * 2) { return x * 2; } // C++11
14/22
auto Keyword - Function Input Type
⋆
4/4
In C++14, auto can be used to define lambda expression inputs
auto lambda = [](auto x) { return x; }
In C++17, auto is used for structure binding
int array[2] = {2, 3};
auto [a, b] = array; // a=2, b=3
In C++20, auto can be used to define function inputs
void f(auto x) {}
// equivalent to templates
f(3); // 'x' is int
f(3.0); // 'x' is double
15/22
C++ Operators
Operators Overview
Precedence Operator Description Associativity
1 a++ a– Suffix/postfix increment and decrement Left-to-right
2
+a -a ++a –a
! ∼
Plus/minus, Prefix increment/decrement,
Logical/Bitwise Not
Right-to-left
3 a*b a/b a%b Multiplication, division, and remainder Left-to-right
4 a+b a-b Addition and subtraction Left-to-right
5 « » Bitwise left shift and right shift Left-to-right
6 < <= > >= Relational operators Left-to-right
7 == != Equality operators Left-to-right
8 & Bitwise AND Left-to-right
9 ˆ Bitwise XOR Left-to-right
10 | Bitwise OR Left-to-right
11 && Logical AND Left-to-right
12 || Logical OR Left-to-right
13
= += -= *= /= %=
«= »= &= ˆ= |=
Assignment and Compound operators Right-to-left
16/22
Operators Precedence 1/2
Operators precedence :
• Unary operators have higher precedence than binary operators
• Standard math operators (+, *, etc.) have higher precedence than
comparison, bitwise, and logic operators
• Bitwise and logic operators have higher precedence than comparison operators
• Bitwise operators have higher precedence than logic operators
• Compound assignment operators += , -= , *= , /= , %= , ^= , != , &= , »= ,
«= have lower priority
• The comma operator has the lowest precedence (see next slides)
17/22
Operators Precedence 2/2
Examples:
a + b * 4; // a + (b * 4)
a * b / c % d; // ((a * b) / c) % d
a + b < 3 >> 4; // (a + b) < (3 >> 4)
a && b && c || d; // (a && b && c) || d
a and b and c or d; // (a && b && c) || d
a | b & c || e && d; // ((a | (b & c)) || (e && d)
Important: sometimes parenthesis can make an expression verbose... but they can
help!
18/22
Prefix/Postfix Increment Semantic
Prefix Increment/Decrement ++i , –i
(1) Update the value
(2) Return the new (updated) value
Postfix Increment/Decrement i++ , i–
(1) Save the old value (temporary)
(2) Update the value
(3) Return the old (original) value
Prefix/Postfix increment/decrement semantic applies not only to built-in types but
also to objects
19/22
Operation Ordering Undefined Behavior
⋆
Reading and modifying a variable within a single expression is bug prone because it can
result in undefined (implementation-defined) behavior:
int i = 0;
i = ++i + 2; // since C++11: i = 3, before: undefined behavior
i = 0;
i = i++ + 2; // since C++17: i = 3, before: undefined behavior
a[i] = ++i; // since C++17: a[1] = 1, before: undefined behavior
f(i = 2, i = 1); // undefined behavior
i = ++i + i++; // undefined behavior
-Wunsequenced raises a warning when multiple unsequenced modifications are made on a
single variable
20/22
Assignment, Compound, and Comma Operators
Assignment and compound assignment operators have right-to-left associativity
and their expressions return the assigned value
int y = 2;
int x = y = 3; // y=3, then x=3
// the same of x = (y = 3)
if (x = 4) // assign x=4 and evaluate to true
The comma operator
⋆
has left-to-right associativity. It evaluates the left expression,
discards its result, and returns the right expression
int a = 5, b = 7;
int x = (3, 4); // discards 3, then x=4
int y = 0;
int z;
z = y, x; // z=y (0), then returns x (4)
21/22
Spaceship Operator <=>
⋆
C++20 provides the three-way comparison operator <=> , also called spaceship
operator, which allows comparing two objects similarly of strcmp . The operator
returns an object that can be directly compared with a positive, 0, or negative integer
value
(3 <=> 5) == 0; // false
('a' <=> 'a') == 0; // true
(3 <=> 5) < 0; // true
(7 <=> 5) < 0; // false
The semantic of the spaceship operator can be extended to any object (see next
lectures) and can greatly simplify the comparison operators overloading
22/22