SlideShare a Scribd company logo
(1) C++ Abstractions 
Nico Ludwig (@ersatzteilchen)
2 
TOC 
● (1) C++ Abstractions 
– Structs as User Defined Datatypes (UDTs) 
– Basic Features of Structs 
– Application Programming Interfaces (APIs) 
– Memory Representation of Plain old Datatypes (PODs) 
● Alignment 
● Layout 
● Arrays of Structs 
● Sources: 
– Bruce Eckel, Thinking in C++ Vol I 
– Bjarne Stroustrup, The C++ Programming Language
3 
Separated Data that is not independent 
● Let's assume following two functions dealing with operations on a date: 
– (The parameters: d for day, m for month and y for year.) 
void PrintDate(int d, int m, int y) { 
std::cout<<d<<"."<<m<<"."<<y<<std::endl; 
} 
void AddDay(int* d, int* m, int* y) { 
/* pass */ 
} 
● We can then use them like this: 
// Three independent ints representing a single date: 
int day = 17; 
int month = 10; 
int year = 2012; 
PrintDate(day, month, year); 
// >17.10.2012 
// Add a day to the date. It's required to pass all the ints by pointer, 
// because an added day could carry over to the next month or year. 
AddDay(&day, &month, &year); 
PrintDate(day, month, year); // The day-"part" has been modified. 
// >18.10.2012
4 
There are Problems with this Approach 
● Yes! The presented solution works! 
– We end in a set of functions (and later also types). 
– Such a set to help implementing software is called an Application Programming Interface (API). 
– An API is a kind of collection of building blocks to create applications. 
● But there are several very serious problems with our way of dealing with dates: 
– We have always to pass three separate ints to different functions. 
– We have to know that these separate ints belong together. 
– The "concept" of a date is completely hidden! - We have "just three ints". 
– So, after some time of developing you have to remember the concept once again! 
– => These are serious sources of difficult-to-track-down programming errors! 
● The problem: we have to handle pieces of data that virtually belong together! 
– The "belonging together" defines the concept that we have to find.
5 
A first Glimpse: User defined Types (UDTs) 
● To solve the problem w/ separated data we'll introduce a User Defined Type (UDT). 
– For the time being we'll create and use a so called struct with the name Date 
– and belonging to functions operating on a Date object/instance/example. 
void PrintDate(Date date) { 
std::cout<<date.day<<"."<<date.month<<"."<<date.year<<std::endl; 
} 
void AddDay(Date* date) { /* pass */ } 
struct Date { 
int day; 
int month; 
int year; 
}; 
● We can use instances of the UDT Date like this: 
– With the dot-notation the fields of a Date instance can be accessed. 
– The functions PrintDate()/AddDay() just accept Date instances as arguments. 
// Three independent ints are stored into one Date object/instance: 
Date today; 
today.day = 17; // The individual fields of a Date can be accessed w/ the dot-notation. 
today.month = 10; 
today.year = 2012; 
PrintDate(today); 
// >17.10.2012 
AddDay(&today); // Add a day to the date. We only need to pass a single Date object by pointer. 
PrintDate(today); // Date's day-field has been modified. 
// >18.10.2012
6 
Basic Features of Structs – Part I 
● C/C++ structs allow defining UDTs. 
– A struct can be defined in a namespace (also the global namespace) or locally. 
– A struct contains a set of fields collecting a bunch of data making up a concept. 
– Each field needs to have a unique name in the struct. 
– The struct Date has the fields day, month and year, all of type int. 
– (UDT-definitions in C/C++ (e.g. structs) need to be terminated with a semicolon!) 
struct Date { 
int day; 
int month; 
int year; 
}; 
struct Person { 
}; 
– The fields of a struct can be of arbitrary type. 
● Fields can be of fundamental type. 
const char* name; 
Date birthday; 
Person* superior; 
● Fields can also be of another UDT! - See the field birthday in the struct Person. 
● Fields can even be of a pointer of the being-defined UDT! - See the field superior in Person. 
– The order of fields doesn't matter conceptually. 
● But the field-order matters as far layout/size of struct instances in memory is concerned.
7 
Basic Features of Structs – Part II 
● A struct can generally be used like any fundamental type: 
– We can create objects incl. arrays of structs. 
● The terms object and instance (also example) of UDTs/structs are often used synonymously. 
– We can get the address of and we can have pointers to struct instances. 
– We can create instances of a struct on the stack or on the heap. 
Date myDate; // Create a Date object on the stack. 
myDate.day = 1; // Set and access a Date's fields w/ the dot notation... 
myDate.month = 2; 
myDate.year = 2012; 
Date someDates[5]; // Create an array of five (uninitialized) Dates. 
Date* pointerToDate = &myDate; // Get the address of a Date instance. 
– Functions can have struct objects as parameters and can return struct objects. 
// A function returning a Date object: 
Date CreateDate(int d, int m, int y) { 
Date date; 
date.day = d; 
date.month = m; 
date.year = y; 
return date; 
} 
// A function accepting a Date object: 
void PrintDay(Date date) { 
/* pass */ 
}
8 
Basic Features of Structs – Part III 
● C++ has a compact initializer syntax to create new struct instances on the stack. 
– Just initialize a new instance with a comma separated list of values put into braces. 
– The instance's fields will be initialized in the order of the list and in the order of their appearance in the struct definition. 
– => The order in the initializer and in the struct definition must match! 
// Initialize a Date object with an initializer: 
Date aDate = {17, 10, 2012}; 
C++11 – uniformed initializers 
Date CreateDate(int d, int m, int y) { 
return {d, m, y}; 
} 
PrintDate({17, 10, 2012}); 
int age{19}; // Also for builtin types. 
// Create a Date object on the stack... 
Date aDate; 
aDate.day = 1; // ...and set its fields w/ the dot 
aDate.month = 2; // notation individually. 
aDate.year = 2012; 
// Ok! The field year will default to 0: 
Date aDate2 = {10, 2012}; 
// Invalid! Too many initializer elements: 
Date aDate3 = {11, 45, 17, 10, 2012}; 
● Instances can also be created directly from a named/anonymous struct definition. 
struct { // Creates an object directly from 
int x, y; // an anonymous struct. 
} point; 
point.x = 3; 
point.y = 4; 
struct Point { // Creates an object directly 
int x, y; // from a struct definition. 
} point; 
point.x = 3; 
point.y = 4;
9 
Basic Features of Structs – Part IV 
● The size of a UDT can be retrieved with the sizeof operator. 
– The size of a UDT is not necessarily the sum of the sizes of its fields. 
● Because of gaps! - More to come in short... 
struct Date { // 3 x 4B 
int day; 
int month; 
int year; 
}; 
std::cout<<sizeof(Date)<<std::endl; 
// >12 
● In C/C++ we'll often have to deal with a pointer to a UDT's instance, e.g.: 
Date aDate = {17, 10, 2012}; 
Date* pointerToDate = &aDate; // Get the address of a Date instance. 
● UDT-pointers are used very often, C/C++ provide special means to work w/ them: 
int day = (*pointerToDate).day; // Dereference pointerToDate and read day w/ the dot. 
int theSameDay = pointerToDate->day; // Do the same with the arrow operator. 
pointerToDate->month = 11; // Arrow: Dereference pointerToDate and write month. 
++pointerToDate->year; // Arrow: Dereference pointerToDate and increment year. 
● The arrow-notation (->) is used very often in C/C++, we have to understand it! 
(*pointerToDate).day pointerToDate->day
10 
UDTs and Instances 
● The idea of a UDT is the invention of a new type, composed of other types. 
– UDTs can be composed of fundamental types and/or composed of other UDTs. 
– => UDTs make APIs really powerful, simple to use and simple to document. 
● In general programming terms UDTs are often called record-types. 
– In C++, record-types can be defined with structs, classes and unions. 
– An API consisting of free functions and record-types is a record-oriented API. 
// Blue print: 
struct Coordinates { 
int x; 
int y; 
}; 
● UDTs and instances: 
// A concrete instance of the blue print 
Coordinates location = {15, 20}; 
// that consumes memory: 
std::size_t size = sizeof(location); 
std::cout<<size<<std::endl; 
// >8 
– A UDT is like a blue print of a prototypical object. 
● E.g. like the fundamental type int is a blue print. 
– An object is a concrete instance of a UDT that consumes memory during run time. 
● E.g. like a variable i or the literal 42 represent instances or objects of the type int. 
C++11 – get the size of a field 
std::size_t size = sizeof(Coordinates::x);
11 
Memory Representation of Structs – PODs 
pi 
struct Fraction { 
int num; 
int denom; 
}; 
Fraction pi; 
● UDTs only containing fields are often called plain old datatypes (PODs). 
– PODs have special features concerning memory we're going to analyze now. 
● Similar to arrays, a struct's fields reside in memory as a sequential block. 
– The Fraction pi is created on the stack, i.e. all its fields are stored on the stack as well. 
– The first field of pi (pi.num) resides on the lowest address, next fields on higher ones. 
– The address of the struct instance (&pi) is the same as of its first field (&pi.num). 
● W/o context, the address of pi could be the address of a Fraction instance or an int. 
– Assigning 22 to pi.num does really assign to the offset of 0B to pi's base address. 
● As pi.denom is 4B above pi.num's address, the 7 is stored to &pi plus an offset of 4B. 
? pi.denom 
? pi.num 
&pi (Fraction*) 
&pi.num (int*) 
4B 
8B 
higher addresses 
pi.num = 22; 
pi.denom = 7; 
7 
22
12 
Memory Representation of Structs – Natural Alignment 
● Many CPU architectures need objects of fundamental type to be naturally aligned. 
– This means that the object's address must be a multiple of the object's size. 
– So, the natural alignment (n.a.) of a type is the multiplicator of its valid addresses. 
● In a UDT, the field w/ the largest n.a. type sets the n.a. of the whole UDT. 
– This is valid for record-types (e.g. structs), arrays and arrays of struct instances. 
– The resulting n.a. is called the n.a. of the UDT. 
– Here some examples (LLVM GCC 4.2, 64b Intel): 
struct A { 
char c; 
}; 
sizeof(A): 1 
Alignment: 1 
struct B { 
char c; 
char ca[3]; 
}; 
sizeof(B): 4 
Alignment: 1 
struct C { 
double d; 
char* pc; 
int i; 
}; 
sizeof(C): 24 
Alignment: 8 
C++11 – get the alignment of a type 
std::size_t alignment = alignof(A); 
std::cout<<alignment<<std::endl; 
// >1 
C++11 – control the alignment of a type 
alignas(double) char array[sizeof(double)]; 
● On a closer look, the size of C seems to be too large! Let's understand why...
13 
Memory Representation of Structs – Layout 
● Field order of T1: the memory layout is sequential, rectangular and contiguous. 
– The field with the largest n.a. (the double a) controls T1's n.a. (8B). 
– Two int-fields can reside at word boundaries and will be packed (2x4B "under" a's 8B). 
– The packed fields lead to a size of 16B for T1. 
● Field order of T2: the memory layout is sequential, rectangular but not contiguous. 
– The field with the largest n.a. (the double a) controls T2's n.a. (also 8B). 
– The n.a. of the fields b and c (ints at word boundaries) causes gaps, this is called padding. 
– This field order leads to a size of 24B for T2. 
● => The order of fields can influence a UDT's size. 
struct T2 { 
int b; 
double a; 
int c; 
}; 
sizeof(T2): 24 
Alignment: 8 
struct T1 { 
double a; 
int b; 
int c; 
}; 
sizeof(T1): 16 
Alignment: 8 T2 
c 
24B a 
b 
T1 
c 
a 
4B 
16B 
b 
higher addresses 
padding bytes
14 
Memory Representation of Structs – Cast Contact Lenses 
Fraction pi; 
pi.num = 22; 
pi.denom = 7; 7 
● The Fraction-object pi is created on the stack. 
&pi.denom (int*) 
● The &pi.denom is really pointing to an int, after the cast it is seen as &Fraction! 
– In other words: &pi.denom is seen as an address of another complete Fraction (*f1). 
– The &pi.denom is now seen as the num field of the overlapping Fraction instance (*f1)! 
Writing f1->num will really write to pi.denom due to the overlap (&pi.denom + 0B) 
– Writing f1->denom will really write to foreign memory (&pi.denom + 4B)! 
– We do not own the memory at &pi.denom + 4B! 
pi 
22 
(Fraction*) 
12 
higher addresses 
? 
7 
*f1 (Fraction) 
f1->num = 12; 
f1->denom = 33; 
Fraction* f1 = reinterpret_cast<Fraction*>(&pi.denom); 
33 
struct Fraction { 12 
int num; 
int denom; 
};
Memory Representation of Structs – Pointer-Fields to Heap 
15 
struct Student { 
char* name; 
char id[8]; 
int nUnit; 
}; 
Student jon; 
● Memory facts of jon: 
jon 
4B 
? 
jon.nUnit 
jon.id 
? jon.name 
16B 
– The address of jon.name (as it is the first field) is also the address of jon. 
– The content of jon.name is not contained in jon, jon.name points to a c-string in heap. 
– The field jon.id occupies 8B, stores a c-string of seven chars and is contained in jon. 
– The field jon.nUnit stores an int that is also contained in jon. 
higher addresses 
const char* name = "Jon"; 
jon.name = static_cast<char*>(std::malloc(sizeof(char) * (1 + std::strlen(name)))); 
std::strcpy(jon.name, name); 
std::strcpy(jon.id, "1234567"); 
jon.nUnit = 21; 
21 
? ? ? ? 
? ? ? ? 
0x00076f2c 
'5' '6' '7' 0 
'1' '2' '3' '4' 'J' 'o' 'n' 0
? ? ? ? 
? ? ? ? 
16 
Memory Representation of Structs – Arrays of Structs 
Student pupils[4]; 
pupils[0].nUnit = 21; 
pupils[2].name = strdup("Adam"); 
'5' ? '? 6' '7' ? '? 
8' 
'1' ? '2' ? '3' ? '4' 
? 
pupils 
? 
? 
? 
? ? ? ? 
? ? ? ? 
? 
● The memory layout of a struct-array is the same as the layout of other arrays. 
● Assigning a pointer to another pointer makes both point to the same memory location. 
● Assigning a c-string leads to occupation of adjacent bytes incl. the 0 termination. 
● Assigning a c-string that overlaps reserved memory overwrites adjacent bytes! 
– This is "ok" in this case: we overwrite only bytes within the array. We are the owner! 
– But the values in the affected Student instances (pupils[0] and pupils[1]) are corrupted. 
? 
? ? ? ? 
? ? ? ? 
? 
? 
? 
21 
'A' 'd' 'a' 'm' 0 
0x0022c680 
pupils[3].name = pupils[2].name; 
std::strcpy(pupils[1].id, "4041543"); 
std::strcpy(pupils[0].id, "123456789ABCDE"); // Oops! 
'5' '4' '3' 0 
'4' '0' '4' '1' 
'D' 'E' 0 ? 0x0022c680 
'9' 'A' 'B' 'C' 
?
17 
Thank you!

More Related Content

Viewers also liked (20)

PPT
2009 South Florida SPCA - Freedom\'s Flight
slpProjects
 
PDF
Sujet1 si-1-centrale-mp-2001
Achraf Ourti
 
DOC
04008 T313 Ind C Tp2
youri59490
 
PPTX
(最終)H26 緩和医療薬学会 シンポジウム 20141001(松山最終)
Yuuji Matsuya
 
PDF
医療連携支援室開設の試み 平田先生
摂 北山
 
PPT
Facebook×採用活動
Kota Saito
 
PDF
Estatísticas do Agile Trends 2013
Dairton Bassi
 
PPTX
1. modulo 3
isvala
 
PDF
Breakthrough column studies for removal of iron ii from groundwater using
IAEME Publication
 
DOC
Qt056
Phi Phi
 
PPT
Facebook採用の課題
Kota Saito
 
PPT
Gmul5063 note 2
ima Ima
 
PDF
Cris rius 18.2.11
Doreen Shaffer
 
ODP
Presentation carrefour test odt
moonheadz
 
PDF
PPCP06 Cap03 parte A
Andre Jun
 
PPTX
死ぬ権利の基本的な考え
UFJmemory
 
DOCX
卒論8 awk1111 石川素 1
Kazuhiko Kawasaki
 
PDF
Sucbenvatlieu41
Phi Phi
 
PDF
0108
Taku Kata
 
2009 South Florida SPCA - Freedom\'s Flight
slpProjects
 
Sujet1 si-1-centrale-mp-2001
Achraf Ourti
 
04008 T313 Ind C Tp2
youri59490
 
(最終)H26 緩和医療薬学会 シンポジウム 20141001(松山最終)
Yuuji Matsuya
 
医療連携支援室開設の試み 平田先生
摂 北山
 
Facebook×採用活動
Kota Saito
 
Estatísticas do Agile Trends 2013
Dairton Bassi
 
1. modulo 3
isvala
 
Breakthrough column studies for removal of iron ii from groundwater using
IAEME Publication
 
Qt056
Phi Phi
 
Facebook採用の課題
Kota Saito
 
Gmul5063 note 2
ima Ima
 
Cris rius 18.2.11
Doreen Shaffer
 
Presentation carrefour test odt
moonheadz
 
PPCP06 Cap03 parte A
Andre Jun
 
死ぬ権利の基本的な考え
UFJmemory
 
卒論8 awk1111 石川素 1
Kazuhiko Kawasaki
 
Sucbenvatlieu41
Phi Phi
 
0108
Taku Kata
 

Similar to (1) cpp abstractions user_defined_types (20)

PDF
Object Oriented Programming (OOP) using C++ - Lecture 1
Faculty of Computers and Informatics, Suez Canal University, Ismailia, Egypt
 
PPTX
CHAPTER -4-class and structure.pptx
GebruGetachew2
 
PPTX
CC213-Week08-User-Defined Data Types.pptx
mahmoud2005rare
 
PDF
(4) c sharp introduction_object_orientation_part_i
Nico Ludwig
 
PDF
New c sharp3_features_(linq)_part_i
Nico Ludwig
 
PDF
C++_notes.pdf
HimanshuSharma997566
 
PPTX
CSC2161Programming_in_Cpp_Lecture4-OOP Classes and Objects[1].pptx
winebaldbanituze
 
PPTX
Chapter 8 Structure Part 2 (1).pptx
Abhishekkumarsingh630054
 
PPTX
Chapter 2 part II array and structure.pptx
abenezertekalign118
 
ODP
(2) cpp imperative programming
Nico Ludwig
 
PPTX
ECE2102-Week13 - 14-Strhhhhhhhjjjucts.pptx
mahmoud2005rare
 
PDF
Object oriented programming with java pdf
sonivipin2342
 
ODP
New c sharp3_features_(linq)_part_i
Nico Ludwig
 
PPTX
Data structure and Algorithms (C++).pptx
ammarasalmanqureshi7
 
PDF
Questions On The Code And Core Module
Katie Gulley
 
PPTX
Chapter 1 Concepts for Object-oriented Databases.pptx
haymanottaddess2015m
 
PPTX
introduction-of-struct-union in deatil.pptx
abhajgude
 
PDF
(2) cpp imperative programming
Nico Ludwig
 
PPTX
С++ without new and delete
Platonov Sergey
 
PDF
С++ without new and delete
Platonov Sergey
 
Object Oriented Programming (OOP) using C++ - Lecture 1
Faculty of Computers and Informatics, Suez Canal University, Ismailia, Egypt
 
CHAPTER -4-class and structure.pptx
GebruGetachew2
 
CC213-Week08-User-Defined Data Types.pptx
mahmoud2005rare
 
(4) c sharp introduction_object_orientation_part_i
Nico Ludwig
 
New c sharp3_features_(linq)_part_i
Nico Ludwig
 
C++_notes.pdf
HimanshuSharma997566
 
CSC2161Programming_in_Cpp_Lecture4-OOP Classes and Objects[1].pptx
winebaldbanituze
 
Chapter 8 Structure Part 2 (1).pptx
Abhishekkumarsingh630054
 
Chapter 2 part II array and structure.pptx
abenezertekalign118
 
(2) cpp imperative programming
Nico Ludwig
 
ECE2102-Week13 - 14-Strhhhhhhhjjjucts.pptx
mahmoud2005rare
 
Object oriented programming with java pdf
sonivipin2342
 
New c sharp3_features_(linq)_part_i
Nico Ludwig
 
Data structure and Algorithms (C++).pptx
ammarasalmanqureshi7
 
Questions On The Code And Core Module
Katie Gulley
 
Chapter 1 Concepts for Object-oriented Databases.pptx
haymanottaddess2015m
 
introduction-of-struct-union in deatil.pptx
abhajgude
 
(2) cpp imperative programming
Nico Ludwig
 
С++ without new and delete
Platonov Sergey
 
С++ without new and delete
Platonov Sergey
 
Ad

More from Nico Ludwig (20)

PPTX
Grundkurs fuer excel_part_v
Nico Ludwig
 
PPTX
Grundkurs fuer excel_part_iv
Nico Ludwig
 
PPTX
Grundkurs fuer excel_part_iii
Nico Ludwig
 
PPTX
Grundkurs fuer excel_part_ii
Nico Ludwig
 
PPTX
Grundkurs fuer excel_part_i
Nico Ludwig
 
PDF
(2) gui drawing
Nico Ludwig
 
ODP
(2) gui drawing
Nico Ludwig
 
PDF
(1) gui history_of_interactivity
Nico Ludwig
 
ODP
(1) gui history_of_interactivity
Nico Ludwig
 
PDF
New c sharp4_features_part_vi
Nico Ludwig
 
PDF
New c sharp4_features_part_v
Nico Ludwig
 
PDF
New c sharp4_features_part_iv
Nico Ludwig
 
ODP
New c sharp4_features_part_iii
Nico Ludwig
 
PDF
New c sharp4_features_part_ii
Nico Ludwig
 
PDF
New c sharp4_features_part_i
Nico Ludwig
 
PDF
New c sharp3_features_(linq)_part_v
Nico Ludwig
 
PDF
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
ODP
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
PDF
New c sharp3_features_(linq)_part_iii
Nico Ludwig
 
PDF
New c sharp3_features_(linq)_part_ii
Nico Ludwig
 
Grundkurs fuer excel_part_v
Nico Ludwig
 
Grundkurs fuer excel_part_iv
Nico Ludwig
 
Grundkurs fuer excel_part_iii
Nico Ludwig
 
Grundkurs fuer excel_part_ii
Nico Ludwig
 
Grundkurs fuer excel_part_i
Nico Ludwig
 
(2) gui drawing
Nico Ludwig
 
(2) gui drawing
Nico Ludwig
 
(1) gui history_of_interactivity
Nico Ludwig
 
(1) gui history_of_interactivity
Nico Ludwig
 
New c sharp4_features_part_vi
Nico Ludwig
 
New c sharp4_features_part_v
Nico Ludwig
 
New c sharp4_features_part_iv
Nico Ludwig
 
New c sharp4_features_part_iii
Nico Ludwig
 
New c sharp4_features_part_ii
Nico Ludwig
 
New c sharp4_features_part_i
Nico Ludwig
 
New c sharp3_features_(linq)_part_v
Nico Ludwig
 
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 
New c sharp3_features_(linq)_part_iii
Nico Ludwig
 
New c sharp3_features_(linq)_part_ii
Nico Ludwig
 
Ad

Recently uploaded (20)

PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
PPTX
Seamless Tech Experiences Showcasing Cross-Platform App Design.pptx
presentifyai
 
PDF
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
PDF
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
PDF
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
PDF
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
Seamless Tech Experiences Showcasing Cross-Platform App Design.pptx
presentifyai
 
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 

(1) cpp abstractions user_defined_types

  • 1. (1) C++ Abstractions Nico Ludwig (@ersatzteilchen)
  • 2. 2 TOC ● (1) C++ Abstractions – Structs as User Defined Datatypes (UDTs) – Basic Features of Structs – Application Programming Interfaces (APIs) – Memory Representation of Plain old Datatypes (PODs) ● Alignment ● Layout ● Arrays of Structs ● Sources: – Bruce Eckel, Thinking in C++ Vol I – Bjarne Stroustrup, The C++ Programming Language
  • 3. 3 Separated Data that is not independent ● Let's assume following two functions dealing with operations on a date: – (The parameters: d for day, m for month and y for year.) void PrintDate(int d, int m, int y) { std::cout<<d<<"."<<m<<"."<<y<<std::endl; } void AddDay(int* d, int* m, int* y) { /* pass */ } ● We can then use them like this: // Three independent ints representing a single date: int day = 17; int month = 10; int year = 2012; PrintDate(day, month, year); // >17.10.2012 // Add a day to the date. It's required to pass all the ints by pointer, // because an added day could carry over to the next month or year. AddDay(&day, &month, &year); PrintDate(day, month, year); // The day-"part" has been modified. // >18.10.2012
  • 4. 4 There are Problems with this Approach ● Yes! The presented solution works! – We end in a set of functions (and later also types). – Such a set to help implementing software is called an Application Programming Interface (API). – An API is a kind of collection of building blocks to create applications. ● But there are several very serious problems with our way of dealing with dates: – We have always to pass three separate ints to different functions. – We have to know that these separate ints belong together. – The "concept" of a date is completely hidden! - We have "just three ints". – So, after some time of developing you have to remember the concept once again! – => These are serious sources of difficult-to-track-down programming errors! ● The problem: we have to handle pieces of data that virtually belong together! – The "belonging together" defines the concept that we have to find.
  • 5. 5 A first Glimpse: User defined Types (UDTs) ● To solve the problem w/ separated data we'll introduce a User Defined Type (UDT). – For the time being we'll create and use a so called struct with the name Date – and belonging to functions operating on a Date object/instance/example. void PrintDate(Date date) { std::cout<<date.day<<"."<<date.month<<"."<<date.year<<std::endl; } void AddDay(Date* date) { /* pass */ } struct Date { int day; int month; int year; }; ● We can use instances of the UDT Date like this: – With the dot-notation the fields of a Date instance can be accessed. – The functions PrintDate()/AddDay() just accept Date instances as arguments. // Three independent ints are stored into one Date object/instance: Date today; today.day = 17; // The individual fields of a Date can be accessed w/ the dot-notation. today.month = 10; today.year = 2012; PrintDate(today); // >17.10.2012 AddDay(&today); // Add a day to the date. We only need to pass a single Date object by pointer. PrintDate(today); // Date's day-field has been modified. // >18.10.2012
  • 6. 6 Basic Features of Structs – Part I ● C/C++ structs allow defining UDTs. – A struct can be defined in a namespace (also the global namespace) or locally. – A struct contains a set of fields collecting a bunch of data making up a concept. – Each field needs to have a unique name in the struct. – The struct Date has the fields day, month and year, all of type int. – (UDT-definitions in C/C++ (e.g. structs) need to be terminated with a semicolon!) struct Date { int day; int month; int year; }; struct Person { }; – The fields of a struct can be of arbitrary type. ● Fields can be of fundamental type. const char* name; Date birthday; Person* superior; ● Fields can also be of another UDT! - See the field birthday in the struct Person. ● Fields can even be of a pointer of the being-defined UDT! - See the field superior in Person. – The order of fields doesn't matter conceptually. ● But the field-order matters as far layout/size of struct instances in memory is concerned.
  • 7. 7 Basic Features of Structs – Part II ● A struct can generally be used like any fundamental type: – We can create objects incl. arrays of structs. ● The terms object and instance (also example) of UDTs/structs are often used synonymously. – We can get the address of and we can have pointers to struct instances. – We can create instances of a struct on the stack or on the heap. Date myDate; // Create a Date object on the stack. myDate.day = 1; // Set and access a Date's fields w/ the dot notation... myDate.month = 2; myDate.year = 2012; Date someDates[5]; // Create an array of five (uninitialized) Dates. Date* pointerToDate = &myDate; // Get the address of a Date instance. – Functions can have struct objects as parameters and can return struct objects. // A function returning a Date object: Date CreateDate(int d, int m, int y) { Date date; date.day = d; date.month = m; date.year = y; return date; } // A function accepting a Date object: void PrintDay(Date date) { /* pass */ }
  • 8. 8 Basic Features of Structs – Part III ● C++ has a compact initializer syntax to create new struct instances on the stack. – Just initialize a new instance with a comma separated list of values put into braces. – The instance's fields will be initialized in the order of the list and in the order of their appearance in the struct definition. – => The order in the initializer and in the struct definition must match! // Initialize a Date object with an initializer: Date aDate = {17, 10, 2012}; C++11 – uniformed initializers Date CreateDate(int d, int m, int y) { return {d, m, y}; } PrintDate({17, 10, 2012}); int age{19}; // Also for builtin types. // Create a Date object on the stack... Date aDate; aDate.day = 1; // ...and set its fields w/ the dot aDate.month = 2; // notation individually. aDate.year = 2012; // Ok! The field year will default to 0: Date aDate2 = {10, 2012}; // Invalid! Too many initializer elements: Date aDate3 = {11, 45, 17, 10, 2012}; ● Instances can also be created directly from a named/anonymous struct definition. struct { // Creates an object directly from int x, y; // an anonymous struct. } point; point.x = 3; point.y = 4; struct Point { // Creates an object directly int x, y; // from a struct definition. } point; point.x = 3; point.y = 4;
  • 9. 9 Basic Features of Structs – Part IV ● The size of a UDT can be retrieved with the sizeof operator. – The size of a UDT is not necessarily the sum of the sizes of its fields. ● Because of gaps! - More to come in short... struct Date { // 3 x 4B int day; int month; int year; }; std::cout<<sizeof(Date)<<std::endl; // >12 ● In C/C++ we'll often have to deal with a pointer to a UDT's instance, e.g.: Date aDate = {17, 10, 2012}; Date* pointerToDate = &aDate; // Get the address of a Date instance. ● UDT-pointers are used very often, C/C++ provide special means to work w/ them: int day = (*pointerToDate).day; // Dereference pointerToDate and read day w/ the dot. int theSameDay = pointerToDate->day; // Do the same with the arrow operator. pointerToDate->month = 11; // Arrow: Dereference pointerToDate and write month. ++pointerToDate->year; // Arrow: Dereference pointerToDate and increment year. ● The arrow-notation (->) is used very often in C/C++, we have to understand it! (*pointerToDate).day pointerToDate->day
  • 10. 10 UDTs and Instances ● The idea of a UDT is the invention of a new type, composed of other types. – UDTs can be composed of fundamental types and/or composed of other UDTs. – => UDTs make APIs really powerful, simple to use and simple to document. ● In general programming terms UDTs are often called record-types. – In C++, record-types can be defined with structs, classes and unions. – An API consisting of free functions and record-types is a record-oriented API. // Blue print: struct Coordinates { int x; int y; }; ● UDTs and instances: // A concrete instance of the blue print Coordinates location = {15, 20}; // that consumes memory: std::size_t size = sizeof(location); std::cout<<size<<std::endl; // >8 – A UDT is like a blue print of a prototypical object. ● E.g. like the fundamental type int is a blue print. – An object is a concrete instance of a UDT that consumes memory during run time. ● E.g. like a variable i or the literal 42 represent instances or objects of the type int. C++11 – get the size of a field std::size_t size = sizeof(Coordinates::x);
  • 11. 11 Memory Representation of Structs – PODs pi struct Fraction { int num; int denom; }; Fraction pi; ● UDTs only containing fields are often called plain old datatypes (PODs). – PODs have special features concerning memory we're going to analyze now. ● Similar to arrays, a struct's fields reside in memory as a sequential block. – The Fraction pi is created on the stack, i.e. all its fields are stored on the stack as well. – The first field of pi (pi.num) resides on the lowest address, next fields on higher ones. – The address of the struct instance (&pi) is the same as of its first field (&pi.num). ● W/o context, the address of pi could be the address of a Fraction instance or an int. – Assigning 22 to pi.num does really assign to the offset of 0B to pi's base address. ● As pi.denom is 4B above pi.num's address, the 7 is stored to &pi plus an offset of 4B. ? pi.denom ? pi.num &pi (Fraction*) &pi.num (int*) 4B 8B higher addresses pi.num = 22; pi.denom = 7; 7 22
  • 12. 12 Memory Representation of Structs – Natural Alignment ● Many CPU architectures need objects of fundamental type to be naturally aligned. – This means that the object's address must be a multiple of the object's size. – So, the natural alignment (n.a.) of a type is the multiplicator of its valid addresses. ● In a UDT, the field w/ the largest n.a. type sets the n.a. of the whole UDT. – This is valid for record-types (e.g. structs), arrays and arrays of struct instances. – The resulting n.a. is called the n.a. of the UDT. – Here some examples (LLVM GCC 4.2, 64b Intel): struct A { char c; }; sizeof(A): 1 Alignment: 1 struct B { char c; char ca[3]; }; sizeof(B): 4 Alignment: 1 struct C { double d; char* pc; int i; }; sizeof(C): 24 Alignment: 8 C++11 – get the alignment of a type std::size_t alignment = alignof(A); std::cout<<alignment<<std::endl; // >1 C++11 – control the alignment of a type alignas(double) char array[sizeof(double)]; ● On a closer look, the size of C seems to be too large! Let's understand why...
  • 13. 13 Memory Representation of Structs – Layout ● Field order of T1: the memory layout is sequential, rectangular and contiguous. – The field with the largest n.a. (the double a) controls T1's n.a. (8B). – Two int-fields can reside at word boundaries and will be packed (2x4B "under" a's 8B). – The packed fields lead to a size of 16B for T1. ● Field order of T2: the memory layout is sequential, rectangular but not contiguous. – The field with the largest n.a. (the double a) controls T2's n.a. (also 8B). – The n.a. of the fields b and c (ints at word boundaries) causes gaps, this is called padding. – This field order leads to a size of 24B for T2. ● => The order of fields can influence a UDT's size. struct T2 { int b; double a; int c; }; sizeof(T2): 24 Alignment: 8 struct T1 { double a; int b; int c; }; sizeof(T1): 16 Alignment: 8 T2 c 24B a b T1 c a 4B 16B b higher addresses padding bytes
  • 14. 14 Memory Representation of Structs – Cast Contact Lenses Fraction pi; pi.num = 22; pi.denom = 7; 7 ● The Fraction-object pi is created on the stack. &pi.denom (int*) ● The &pi.denom is really pointing to an int, after the cast it is seen as &Fraction! – In other words: &pi.denom is seen as an address of another complete Fraction (*f1). – The &pi.denom is now seen as the num field of the overlapping Fraction instance (*f1)! Writing f1->num will really write to pi.denom due to the overlap (&pi.denom + 0B) – Writing f1->denom will really write to foreign memory (&pi.denom + 4B)! – We do not own the memory at &pi.denom + 4B! pi 22 (Fraction*) 12 higher addresses ? 7 *f1 (Fraction) f1->num = 12; f1->denom = 33; Fraction* f1 = reinterpret_cast<Fraction*>(&pi.denom); 33 struct Fraction { 12 int num; int denom; };
  • 15. Memory Representation of Structs – Pointer-Fields to Heap 15 struct Student { char* name; char id[8]; int nUnit; }; Student jon; ● Memory facts of jon: jon 4B ? jon.nUnit jon.id ? jon.name 16B – The address of jon.name (as it is the first field) is also the address of jon. – The content of jon.name is not contained in jon, jon.name points to a c-string in heap. – The field jon.id occupies 8B, stores a c-string of seven chars and is contained in jon. – The field jon.nUnit stores an int that is also contained in jon. higher addresses const char* name = "Jon"; jon.name = static_cast<char*>(std::malloc(sizeof(char) * (1 + std::strlen(name)))); std::strcpy(jon.name, name); std::strcpy(jon.id, "1234567"); jon.nUnit = 21; 21 ? ? ? ? ? ? ? ? 0x00076f2c '5' '6' '7' 0 '1' '2' '3' '4' 'J' 'o' 'n' 0
  • 16. ? ? ? ? ? ? ? ? 16 Memory Representation of Structs – Arrays of Structs Student pupils[4]; pupils[0].nUnit = 21; pupils[2].name = strdup("Adam"); '5' ? '? 6' '7' ? '? 8' '1' ? '2' ? '3' ? '4' ? pupils ? ? ? ? ? ? ? ? ? ? ? ? ● The memory layout of a struct-array is the same as the layout of other arrays. ● Assigning a pointer to another pointer makes both point to the same memory location. ● Assigning a c-string leads to occupation of adjacent bytes incl. the 0 termination. ● Assigning a c-string that overlaps reserved memory overwrites adjacent bytes! – This is "ok" in this case: we overwrite only bytes within the array. We are the owner! – But the values in the affected Student instances (pupils[0] and pupils[1]) are corrupted. ? ? ? ? ? ? ? ? ? ? ? ? 21 'A' 'd' 'a' 'm' 0 0x0022c680 pupils[3].name = pupils[2].name; std::strcpy(pupils[1].id, "4041543"); std::strcpy(pupils[0].id, "123456789ABCDE"); // Oops! '5' '4' '3' 0 '4' '0' '4' '1' 'D' 'E' 0 ? 0x0022c680 '9' 'A' 'B' 'C' ?

Editor's Notes

  • #6: Arrays are also UDTs! The phrase &amp;quot;belonging to function&amp;quot; can be clearly explained now, e.g. the function PrintDate() depends on the bare presence of the definition of the UDT Date! Why do we need to pass a Date by pointer to the function AddDay()? Because AddDay() needs to modify the passed Date.
  • #7: In C# and Java, the syntactic definitions of UDTs are not terminated by semicolons!
  • #8: In a future lecture we&amp;apos;ll learn how to create UDTs on the heap.
  • #9: The initializer syntax for structs can also be used for builtin types: int age = {29};
  • #12: Definitions: num := numerator, denom := denominator A very stringent definition of PODs: A POD contains only fields of fundamental type; this makes a PODs self-contained. Self-contained PODs have no dependencies to other UDTs that makes using them very straight forward (this is esp. relevant for tool support). Meanwhile C++11 provides a less stringent definition of PODs. The necessity of a struct&amp;apos;s fields being arranged at sequential addresses (incl. the first field having the lowest address, representing the address of a struct instance) doesn&amp;apos;t hold true, if a UDT applies access specifiers (private, protected and public).
  • #14: In .Net the memory representation of structs (value types) can be controlled with the custom attribute StructLayout.
  • #15: Pointer arithmetics only work with arrays. This feature is exploited for STL operations.
  • #16: In which kind of memory is jon.name stored? And where is the memory, to which jon.name is pointing to? The field jon.name is special, as it only contains a pointer to the &amp;quot;real&amp;quot; c-string (the pointer (the &amp;quot;cord&amp;quot;) resides on the stack). The memory occupied by this c-string (the &amp;quot;balloon&amp;quot;) resides somewhere in the heap. The address stored in jon.name is also the address of the c-string&amp;apos;s first char. It also means that the memory at jon.name needs to be freed after we&amp;apos;re done with jon! Why has the char* a size of 4B? The size of all pointer types is the size of the architecture&amp;apos;s address space. On a 32-bit system: 4 = sizeof(int*), on a 64-bit system: 8 = sizeof(int*), etc. The address of jon could be a Student* or char**.
  • #17: In which kind of memory is the array pupils stored? Why is the function strdup() not prefixed with std? This function is not in the namespace std, because it is no C++ standard function. But it is defined in the POSIX &amp;quot;standard&amp;quot;. What is POSIX? The Portable Operating System Interface (POSIX) is an IEEE- and Open Group-standard for a platform-independent API to operate with the OS. If two pointers point to the same location in the heap, the memory must only be freed from one of those pointers!