0% found this document useful (0 votes)
4K views35 pages

03.basic Concepts I

Uploaded by

yatoabesta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4K views35 pages

03.basic Concepts I

Uploaded by

yatoabesta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

Modern C++

Programming
2. Basic Concepts I
Type System, Fundamental Types, and Operators

Federico Busato
2024-03-29
Table of Contents

1 The C++ Type System


Type Categories
Type Properties ⋆

2 Fundamental Types Overview


Arithmetic Types
Suffix and Prefix
Non-Standard Arithmetic Types
void Type
nullptr

1/29
Table of Contents

3 Conversion Rules

4 auto Keyword

5 C++ Operators
Operators Precedence
Prefix/Postfix Increment/Decrement Semantic
Assignment, Compound, and Comma Operators
Spaceship Operator <=> ⋆

Safe Comparison Operators ⋆

2/29
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/29
Type Categories

C++ organizes the language types in two main categories:

• Fundamental types: Types provided by the language itself


• Arithmetic types: integer and floating point
• void
• nullptr C++11

• Compound types: Composition or references to other types


• Pointers
• References
• Enumerators
• Arrays
• struct , class , union
• Functions
4/29

Type Properties 1/2

C++ types can be also classified based on their properties:

• 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.
Types: Arithmetic, Pointers and nullptr , Enumerators, Arrays, struct ,
class , union

5/29

Type Properties 2/2

• 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
Types: Arithmetic, Pointers and nullptr , Enumerators

• Trivial types: Trivial default/copy constructor, copy assignment operator, and


destructor → Trivially Copyable
Types: Scalar, trivial class types, arrays of such types

• Incomplete types: A type that has been declared but not yet defined
Types: void , incompletely-defined object types, e.g. struct A; , array of elements of
incomplete type
6/29
C++ Types Summary

7/29
Fundamental Types
Overview
Arithmetic Types - Integral

Fixed width types


Native Type Bytes Range
<cstdint>

bool 1 true, false


char † 1 implementation defined
signed char 1 -128 to 127 int8 t
unsigned char 1 0 to 255 uint8 t
short 2 -215 to 215 -1 int16 t
unsigned short 2 0 to 216 -1 uint16 t
int 4 -231 to 231 -1 int32 t
unsigned int 4 0 to 232 -1 uint32 t
long int 4/8∗ int32 t/int64 t
long unsigned int 4/8∗ uint32 t/uint64 t
long long int 8 -263 to 263 -1 int64 t
long long unsigned int 8 0 to 264 -1 uint64 t

∗ † 8/29
4 bytes on Windows64 systems, signed/unsigned, two-complement from C++11
Arithmetic Types - Floating-Point

Fixed width types


Native Type IEEE Bytes Range
C++23 <stdfloat>

(bfloat16) N 2 ±1.18 × 10−38 to ±3.4 × 10+38 std::bfloat16 t

(float16) Y 2 0.00006 to 65, 536 std::float16 t

float Y 4 ±1.18 × 10−38 to ±3.4 × 10+38 std::float32 t

double Y 8 ±2.23 × 10−308 to ±1.8 × 10+308 std::float64 t

9/29
Arithmetic Types - Short Name

Signed Type short name

signed char /
signed short int short
signed int int
signed long int long
signed long long int long long

Unsigned Type short name

unsigned char /
unsigned short int unsigned short
unsigned int unsigned
unsigned long int unsigned long
unsigned long long int unsigned long long 10/29
Arithmetic Types - Suffix (Literals)

Type SUFFIX Example Notes


int / 2
unsigned int u, U 3u
long int l, L 8L
long unsigned ul, UL 2ul
long long int ll, LL 4ll
long long unsigned int ull, ULL 7ULL
float f, F 3.0f only decimal numbers
double 3.0 only decimal numbers

C++23 Type SUFFIX Example Notes


std::bfloat16 t bf16, BF16 3.0bf16 only decimal numbers
std::float16 t f16, F16 3.0f16 only decimal numbers
std::float32 t f32, F32 3.0f32 only decimal numbers
std::float64 t f64, F64 3.0f64 only decimal numbers
std::float128 t f128, F128 3.0f128 only decimal numbers
11/29
Arithmetic Types - Prefix (Literals)

Representation PREFIX Example

Binary C++14 0b 0b010101


Octal 0 0307
Hexadecimal 0x or 0X 0xFFA010

C++14 also allows digit separators for improving the readability 1'000'000

12/29
Other 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 )

13/29
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
}

14/29
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

15/29
Conversion Rules
Conversion Rules

Implicit type conversion rules, applied in order, before any operation:


⊗: any operation (*, +, /, -, %, etc.)
(A) Floating point promotion
floating type ⊗ integer type → floating type

(B) Implicit integer promotion


small integral type := any signed/unsigned integral type smaller than int
small integral type ⊗ small integral type → int

(C) Size promotion


small type ⊗ large type → large type

(D) Sign promotion


signed type ⊗ unsigned type → unsigned type 16/29
Examples and Common Errors

float f = 1.0f;
unsigned u = 2;
int i = 3;
short s = 4;
uint8_t c = 5; // unsigned char

f * u; // float × unsigned → float: 2.0f


s * c; // short × unsigned char → int: 20
u * i; // unsigned × int → unsigned: 6u
+c; // unsigned char → int: 5

Integers are not floating points!


int b = 7;
float a = b / 2; // a = 3 not 3.5!!
int c = b / 2.0; // again c = 3 not 3.5!!
17/29
Implicit Promotion

Integral data types smaller than 32-bit are implicitly promoted to int , independently
if they are signed or unsigned
• Unary +, -, ∼ and Binary +, -, &, etc. promotion:

char a = 48; // '0'


cout << a; // print '0'
cout << +a; // print '48'
cout << (a + 0); // print '48'

uint8_t a1 = 255;
uint8_t b1 = 255;
cout << (a1 + b1); // print '510' (no overflow)

18/29
auto Keyword
auto Keyword 1/3

C++11 The auto keyword specifies that the type of the variable will be automatically
deduced by the compiler (from its initializer)
auto a = 1 + 2; // 1 is int, 2 is int, 1 + 2 is int!
// -> 'a' is "int"
auto b = 1 + 2.0; // 1 is int, 2.0 is double. 1 + 2.0 is double
// -> 'b' is "double"

auto can be very useful for maintainability and for hiding complex type definitions
for (auto i = k; i < size; i++)
...

On the other hand, it may make the code less readable if excessively used because of
type hiding
Example: auto x = 0; in general makes no sense ( x is int )
19/29

auto Keyword - Functions 2/3

In C++11/C++14, auto (as well as decltype ) can be used to define function


output types
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

auto h(int x) { return x * 2; } // C++14

//--------------------------------------------------------------

int x = g(3); // C++11

20/29

auto Keyword - Functions 3/3

In C++20, auto can be also used to define function input


void f(auto x) {}
// equivalent to templates but less expensive at compile-time

//--------------------------------------------------------------

f(3); // 'x' is int


f(3.0); // 'x' is double

21/29
C++ Operators
Operators Overview

Precedence Operator Description Associativity

1 a++ a-- Suffix/postfix increment and decrement Left-to-right


+a -a ++a --a Plus/minus, Prefix increment/decrement,
2 Right-to-left
! not ∼ Logical/Bitwise Not
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 && and Logical AND Left-to-right
12 || or Logical OR Left-to-right
+= -= *= /= %=
13 Compound Right-to-left
<<= >>= &= ˆ= |= 22/29
Operators Precedence 1/2

• 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)

23/29
en.cppreference.com/w/cpp/language/operator precedence
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! 24/29
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
25/29

Operation Ordering Undefined Behavior

Expressions with undefined (implementation-defined) behavior:


int i = 0;
i = ++i + 2; // until C++11: undefined behavior
// since C++11: i = 3
i = 0;
i = i++ + 2; // until C++17: undefined behavior
// since C++17: i = 3

f(i = 2, i = 1); // until C++17: undefined behavior


// since C++17: i = 2
i = 0;
a[i] = ++i; // until C++17: undefined behavior
// since C++17: a[1] = 1

f(++i, ++i); // undefined behavior


i = ++i + i++; // undefined behavior 26/29
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) 27/29

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

28/29

Safe Comparison Operators

C++20 introduces a set of functions <utility> to safely compare integers of


different types (signed, unsigned)
bool cmp_equal(T1 a, T2 b)
bool cmp_not_equal(T1 a, T2 b)
bool cmp_less(T1 a, T2 b)
bool cmp_greater(T1 a, T2 b)
bool cmp_less_equal(T1 a, T2 b)
bool cmp_greater_equal(T1 a, T2 b)
example:
# include <utility>
unsigned a = 4;
int b = -3;
bool v1 = (a > b); // false!!!, see next slides
bool v2 = std::cmp_greater(a, b); // true
29/29
How to compare signed and unsigned integers in C++20?

You might also like