0% found this document useful (0 votes)
132 views53 pages

Advanced Systems Programming:: Marcus Völp

This document summarizes a lecture on advanced C++ types, pointers, and pointer arithmetic given by Marcus Völp. The schedule outlines parts on C++ types, inheritance, operators, storage and scope. Part I introduces fundamental and compound C++ types like classes, structs, unions, arrays, and typedefs. It also covers pointers and references. The first practical exercise involves implementing a linked list.

Uploaded by

mindq007
Copyright
© Attribution Non-Commercial (BY-NC)
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)
132 views53 pages

Advanced Systems Programming:: Marcus Völp

This document summarizes a lecture on advanced C++ types, pointers, and pointer arithmetic given by Marcus Völp. The schedule outlines parts on C++ types, inheritance, operators, storage and scope. Part I introduces fundamental and compound C++ types like classes, structs, unions, arrays, and typedefs. It also covers pointers and references. The first practical exercise involves implementing a linked list.

Uploaded by

mindq007
Copyright
© Attribution Non-Commercial (BY-NC)
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/ 53

Department of Computer Science, Institute for System Architecture, Operating Systems Group

Advanced Systems Programming:


C++ Types, Pointer, Pointer Arithmetic

Marcus Völp
Schedule for today

• now Part I: A brief introduction to C++


• ~ 10:30 Practical Exercise I:
a first list
• ~ 13:00 Lunch

• ~ 14:00 Part II: More C++:


Inheritance, Casts
• ~ 14:30 Practical Exercise II: More lists
• ~ 15:00 Part III: Even More C++
Operators, Overloading, Evaluation Order
• ~ 15:45 Part IV: Oh no, more C++
(or tomorrow) Storage, Scope and Object Lifetime
• Wrap up

October, 2nd 2009 Marcus Völp 2


Outline – Part I

• C++ Types
– fundamental types
– class, struct, bitfields
– union
– arrays
– typedef and new types

• Pointers + References
– Introduction

• Practical Exercises: lists

October, 2nd 2009 Marcus Völp 3


Outline – Part I <complex1.cc>

• C++ Types
– fundamental types
– class, struct, bitfields
– union
– arrays
– typedef and new types

• svn
Pointers + References
co http://svn.inf.tu-dresden.de/repos/advsysprog/day2/examples_lecture
– Introduction

• Practical Exercises: lists

October, 2nd 2009 Marcus Völp 4


C++ Types

Types
• define the operations that are permitted on an object
• define the size of the object representation

y = x;
y = x + 42;
y = f(x);

• compare

int y = x + 42; vs. Complex y = x + 42;

Complex := (r, i) ; Complex c + int n := (c.r + n, c.i)

October, 2nd 2009 Marcus Völp 5


C++ Types

• Example: Complex numbers

– The Real World: (math) ℝ x ℝ

– C++ Code: class Complex { int real ; int imag; } :

• some weird programmer (Marcus) decided not to use floats


– double  ℝ
• any integral number between INT_MIN and INT_MAX

the standard requires each implementation to define these constants.

– C++ Implementation: e.g., GCC – x86 - linux:


• sizeof(int) == 4 [chars] ;

• char has at least 8 bits (possibly more)


• arithmetic follows two's complement 0xffffffff = -1
(possibly also ones' complement, etc. 0xffffffff = 0)

– Still, some behavior remains undefined*:


• Complex c;
• &c.real < &c.imag

* more on this later!


October, 2nd 2009 Marcus Völp 6
C++ Types

C++ Standard: [3.9.1]

• Adherence to standard => good programs

October, 2nd 2009 Marcus Völp 7


C++ Types

• fundamental types:

– char contains implementation basic character set (UTF8)

– integers integer numbers

• signed char ⊆ short int ⊆ int ⊆ long int ⊆ long long int

• unsigned integers:
– nonnegative signed range ⊆ unsigned range
– nonnegative values represented by the same bit pattern as
signed
– arithmetic modulo 2^n

– bool true / false

– floating point float, double, long double

– void type with empty set of values

October, 2nd 2009 Marcus Völp 8


C++ Types

• compound types: (any combination of)

– arrays of type T N objects of same type T

– functions N parameter types + return type

– pointers of type T stores “an arrow” to an object of type T

– references a different name for an object


(may require storage)

– classes, structs members can have different types


access restrictions

– unions members can have different types,


only one type is current,
no type-tag information with object

– enumerations set of named constants


(subset of some integral type)

– pointers to non-static class members

October, 2nd 2009 Marcus Völp 9


Classes, Structs, Bitfields <complex1.cc>

A class defines new type:

class Complex {
private:
int _real; fundamental type: int
int _imag;

public:
void add(int n); compound type: void (Complex::)(int)
};

Access restrictions:
public – everyone
private – only class members, (friends - later)
protected - only class and derived classes

class: default access restriction = private


struct: default access restriction = public
union: public members, holds only one data member at a time

October, 2nd 2009 Marcus Völp 10


Classes, Structs, Bitfields <complex1.cc>

A class defines new type:

class Complex {
private:
int _real; fundamental type: int
int _imag;

public:
void add(int n); compound type: void (Complex::)(int)
};

Access restrictions:
public – everyone
private – only class members, (friends - later)
protected - only class and derived classes

class: default access restriction = private


struct: default access restriction = public
union: public members, holds only one data member at a time

October, 2nd 2009 Marcus Völp 11


typedef vs. new types <typedef.cc>

class S { typedef int S;


int x; typedef int T;
};
S a;
class T { T b;
int y;
}; b = a;

S a;
T b;

b = a;

October, 2nd 2009 Marcus Völp 12


C++ Types

C++ Standard: [9.2 – clause 12, pg. 180]

• Nonstatic data members of a (non-union) class declared without an intervening


access-specifier are allocated so that later members have higher addresses
within a class object. The order of allocation of non-static data members
separated by an access-specifier is unspecified (11.1 ). Implementation
alignment requirements might cause two adjacent members not to be
allocated immediately after each other; so might requirements for space for
managing virtual functions (10.3 ) and virtual base classes (10.1 ).

class Pack1 { struct Pack2 { struct Pack3 {


public: char a; char c;
char a; char b; char a;
char b; char c; char b;
private: }; };
char c;
};

• GCC seems to always chose the same layout for Pack1 and Pack2!

October, 2nd 2009 Marcus Völp 13


Bitfields <pte.cc>

Bit Fields:
0 31
ptab_base avail p

p avail ptab_base

struct page_table_entry {
unsigned present : 1;
unsigned avail : 11; /* 8-bit char + 3-bit padding */
unsigned base : 20;
};

alternatively:
unsigned avail : 8;
: 3; /* padding */

packed attribute (Gcc extension)


pack datatypes more densely

struct page_table entry {


...
} __attribute__ ((packed));
October, 2nd 2009 Marcus Völp 14
Pointers and References

char c = 'M';
char* p = &c; /* pointer to c */
char& r = c; /* reference to c */

p:

c: 'M'
r:

Pointer: a thing (p) that points to some object (e.g., c)


Reference: another name for an initialized object (c, r name the same object)

Null pointer: char* p = 0;

class C {...};

C c; object on stack
C* p = new C(); pointer to object on heap
C* p = &c; pointer to existing object

delete p; free object on heap

October, 2nd 2009 Marcus Völp 15


C++ Types

Advice [AS -NoP – 5, pg 43]:


• types exist irrespective of the programming language

=> design data structures and algorithms first


the mapping to the language is the second step

[AS – NoP – 5, pg 43] =


Alexander Stepanov: Notes on Programming Lecture 5 pg. 43

Advice [St - 4.10]


• Choose names carefully to reflect meaning rather than implementation
• Use:
– typedefs to define synonyms;
– enum to define constants
– class to define new types

Advice [St – 10.5]


• Represent concepts as classes
• Use public (structs) only when members are really just data and only if no
invariants must be maintained.

October, 2nd 2009 Marcus Völp 16


Exercise 1: linked lists

Implement a linked list of complex numbers:

Provide the following functions:

- insert a given element at the head of the list


- insert a given element at the tail
- remove a given element (possibly from the middle)
- set / get complex value of a given element
- search an element that matches a given complex number (if present)
- provide the sum of all complex numbers in the list
(yes, that's an instance of the generic folding function over lists)

Choose an appropriate data structure!

October, 2nd 2009 Marcus Völp 17


Exercise 1: linked lists

1) single-linked list

2) single-linked list with head element

3) double-linked list

4) double-linked list cyclic

5) double-linked list cyclic with head element


H
October, 2nd 2009 Marcus Völp 18
Exercise 1: linked lists

sum
- iterate list and sum up elements individually vs.
- maintain sum at list head

reduce (towards a generic folding function; more later)


- Complex null_function ()
(sum: return 0;)

- Complex cons_function (Complex tail_result, Complex current)


(sum: return tail_result + current)

October, 2nd 2009 Marcus Völp 19


Outline Part II

• Friends

• Inheritance + Casts
– static cast, reinterpret cast
– dynamic cast

• Pointer to arrays
– pointer arithmetic
– ring buffer (Hacking: optional)

• Trees (Hacking: optional)

October, 2nd 2009 Marcus Völp 20


Friends <friend.cc>

Problem: access private fields of closely related class

class ListElement {
private:
ListElement * _next;
};

...
void List::insert_head (ListElement * elem) {
elem->_next = _head;
_head = elem;
}

Solution: make List::insert_head friend of List

class ListElement {
friend void List::insert_head (ListElement * elem);
friend class List; /* all members of List are friends of ListElement */

};

October, 2nd 2009 Marcus Völp 21


Inheritance

class Insect {
public: Insect
static unsigned int const number_of_legs = 6; number of legs = 6
};

class Bee : public Insect {


void hum(); Bee
};

Bee b;
unsigned int foo = b.number_of_legs;

October, 2nd 2009 Marcus Völp 22


Casts <inheritance.cc>

Casts

Insect* i = new Bee(); - implicit conversion of derived class


to base class

Bee* b = static_cast<Bee*>(i); - explicit unchecked conversion

Moscito* m = static_cast<Moscito*>(i);

Bee* b2 = dynamic_cast<Bee*>(i); - check whether I is of type Bee


return 0 otherwise
(needs RTTI)

unsigned int addr = 42;


Bee* b3 = reinterpret_cast<Bee*>(addr); - reinterpret the bit pattern at addr

!!! the object representation at addr may change [§ 5.2.10 pt. 3]

October, 2nd 2009 Marcus Völp 23


Inheritance

Insect Flying_thing
number of legs = 6 void fly()

Bee Aerodyn. Notebook

Aerodyn. Thinkpad

• Generic Interface
• Generic Implementation
• Different implementation for each derived class

October, 2nd 2009 Marcus Völp 24


Inheritance Java vs. C++ <inheritance2.cc>

Interface FlyingThing (in a minute)

virtual void fly() vs.


void fly2()

Aerodyn_notebook * aero_notebook;

aero_notebook fly fly2


= new Aerodyn_nodebook(); Aerodyn_nodebook Aerodyn_nodebook
= new Aerodyn_thinkpad(); Aerodyn_thinkpad Aerodyn_nodebook

October, 2nd 2009 Marcus Völp 25


Abstract Base Class <inheritance2.cc>

Insect Flying_thing
number of legs = 6 void fly()

Bee Aerodyn. Notebook

class Flying_things {
virtual void fly() = 0; => Bee must implement void fly()
} to become non virtual

Flying_things * flying_thing = new Flying_things(); /* ERROR */

October, 2nd 2009 Marcus Völp 26


Construction / Destruction (take 1) <complex3.cc>

class Complex {
int _real;
int _imag;
public:
void init();
};

void Complex::init()
{
_real = 42; _imag = 0;
}

• problem: init may not be called


• make explicit that init is called for newly created objects

class Complex {
public:
Complex(); /* Default Constructor for Complex */
Complex(const Complex& c); /* Copy Constructor */
Complex(int real, int imag); /* Initialising Constructor */
Complex(int real); /* Conversion from int to Complex */
}
October, 2nd 2009 Marcus Völp 27
Construction / Destruction (take 1)

How to clean up? --- deleting objects

delete middle;

class List_Element {
public:
~List_Element();
};

List_Element::~List_Element()
{
remove();
}

October, 2nd 2009 Marcus Völp 28


Construction / Destruction (take 1)

Advice [ST – 10.5]


• Use a constructor to establish invariants

e.g., “My_complex numbers have integer reals between 10 ... 100”


– My_complex() { _real = 10 }
– add(int n) { _real = ((_real + n – 10) % 90) + 10;}

• Release all resources in the destructor


• If a class needs a copy operation or a destructor it probably also needs a
constructor, a destructor, a copy assignment and a copy constructor
!!! otherwise make them private to prevent copying !!!

• Carefully copy all elements if you implement a copy constructor

• Construct objects with members by explicitly invoking


the member's constructors

– List(T* item): _item(item) {} not List(T* item) { _item = 0 }

– constructors of members must be called in the order in which they are


defined
– Later: initialization of const members

October, 2nd 2009 Marcus Völp 29


Exercise 2: more linked lists

• add Constructors / Destructors to class Complex

• add Constructors / Destructors to List and ListElement

• List with head element --- List : public ListElement

• Make allocation / deallocation of list elements implicit

October, 2nd 2009 Marcus Völp 30


Outline Part III

• Arrays

• Operator Overloading
– overloading && for non base types

• void *

• const qualifier, pointer to const, const cast

• References
– call by value vs. call by reference
– self reference

October, 2nd 2009 Marcus Völp 31


Pointer to Array ; Pointer Arithmetic

T a[6];

October, 2nd 2009 Marcus Völp 32


Pointer to Array ; Pointer Arithmetic

T a[6];

sizeof(T)

T a[6][2];

T
T

October, 2nd 2009 Marcus Völp 33


Pointer to Array ; Pointer Arithmetic

T a[6];

T a[6][2];

T
T

T a[3][4];
T
T
T

October, 2nd 2009 Marcus Völp 34


Pointer to Array ; Pointer Arithmetic

T a[6];

p = &a[-1] m = &a[3] e = &a[6]


f = &a[0]

p illegal – avoid it
e legal pointer to end of array – do not dereference
*e undefined
m' = m + 1 next element in the array that follows *m
this is NOT m + sizeof(T) but &(*m) + sizeof(T)
m–f number of elements of type T in between m and f (here 3)

Common use of pointer arithmetic: array iteration


for (m = f; m < e; m++) ...

Advice [ST – 5.8]: Avoid nontrivial pointer arithmetic !!! DOCUMENT IT !!!
October, 2nd 2009 Marcus Völp 35
Operator Overloading <overloading.cc>

Operators:
+ | - | * | / | % | ^ | & | | | ~ | ! | = | < | > | += | -= | *= | /= | %= | ^= | &= | |= |
<< | >> | >>= | <<= | == | != | <= | >= | && | || | ++ | -- | ->* | , | -> | [] | () |
new | new[] | delete | delete[]

Example:
Complex a, b, c;
c = a + b; c = add(a,b)
c = 7; c = Complex(7); Constructor for
int to complex conversion

Your own operators:


class Complex {
...
Complex operator + (Complex b); member version takes
one argument
};

Complex operator + (Complex a, Complex b); nonmember version takes


two arguments

October, 2nd 2009 Marcus Völp 36


Operator Overloading <overloading.cc>

Operators:
+ | - | * | / | % | ^ | & | | | ~ | ! | = | < | > | += | -= | *= | /= | %= | ^= | &= | |= |
<< | >> | >>= | <<= | == | != | <= | >= | && | || | ++ | -- | ->* | , | -> | [] | () |
new | new[] | delete | delete[]

Iterators:

List_element le;
le++; le--; le->f_T(); le = le->next(); le = le->prev(); le->item()->f_T();

Allocators:

void* operator new(Allocator * allocator, size_t size);


Compex C* = new(allocator) Complex(42);

There is no way to specify the allocator in delete

=> delete operator must know the allocator

October, 2nd 2009 Marcus Völp 37


Overloading && <and_overload.cc>

f : Function returning element of type T with side effect (e.g., side_effect++)

class T {
public:
unsigned int val;
};

bool operator&&(T t1, T t2);

bool b1 = f() && f();

bool b2 = f().val && f().val;

October, 2nd 2009 Marcus Völp 38


Void *
Pointer of unknown type: void *

int * pi;

void* pv = pi; [§ 4.10 pt 2]


pv is a pointer to the storage of *pi

int* pi2 = static_cast<int*>(pv); [§ 5.2.9 pt 10]

Typical use:

void* malloc(size_t n);

void* operator new(size_t n);

October, 2nd 2009 Marcus Völp 39


Const
const qualifier:

Give a hint to the compiler that the object will not be modified!

Const objects may still need storage if the compiler cannot derive
that they are remain constant!

int const the_answer = 42;


int const v[] = {1, 2, 3, 4}; v[i] is const
T::f () const member function f does not modify the object

pointers and const (or where to put the qualifier)

int const * c; nonconstant pointer to a constant int


int * const cp; constant pointer to a nonconstant int
int const * const ccp constant pointer to a constant int

const_cast cast away constness

int const c;
int i = const_cast<int>(c);

October, 2nd 2009 Marcus Völp 40


Const <const_init.cc>

Constructors Revisited

class Aerodyn_notebook {
unsigned int const _memory;
unsigned int const _cpu_freq;

Aerodyn_notebook(unsigned int memory, unsigned int cpu_freq) {


_memory = memory; /* error: assignment of read-only data-member */
_cpu_freq = cpu_freq;
}

/* Use member constructors */


Aerodyn_notebook(unsigned int memory, unsigned int cpu_freq) :
_memory(memory), _cpu_freq(cpu_freq)
{}
};

October, 2nd 2009 Marcus Völp 41


References <matrix.cc>

call by value vs. call by reference

class Matrix {
unsigned int _data[200][200];
}

Matrix operator + (Matrix const a, Matrix const b);

Matrix operator + (Matrix const &a, Matrix const &b);

self reference

class Matrix {
Matrix operator + (const Matrix & a)
}

Matrix Matrix::operator + (const Matrix & a)


{
/* add implementation */
return *this;
}

October, 2nd 2009 Marcus Völp 42


Practical Exercise III:

• const / references for our list

• operators for our list


– towards an iterator

October, 2nd 2009 Marcus Völp 43


Outline Part IV

• Underlying Storage
– object lifetime

• Scope
– lock guards

October, 2nd 2009 Marcus Völp 44


Storage and Object Lifetime
• C++ Memory Model
– Byte-wise memory model
– Object = region of storage
– Each object has a storage duration which influences lifetime

• static storage Code / Data Section


• automatic storage Stack
• dynamic storage Heap

Code Data Heap Stack

October, 2nd 2009 Marcus Völp 45


Storage and Object Lifetime

Static storage
• non local, not dynamically created objects

int global;

int main(int ...

class X {
static unsigned int count_of_x;
}

int foo() { static int s = 42; }

• Object is allocated in the data segment

October, 2nd 2009 Marcus Völp 46


Storage and Object Lifetime

Automatic storage
• local objects, auto / register

int foo () {
int local;

return 42;
}

int bar() { int bar() {


C foo = C(); C foo = C();

return 42; return_value = 42;


} foo.~C();
return return_value;
}
• Object is allocated on the stack
• Lifes until scope is exited

October, 2nd 2009 Marcus Völp 47


Scope

{} defines a scope

int foo () {
/* begin scope of foo */
if () {
/* begin scope of if case */

/* end scope of if case */


} else {
/* begin scope of else case */

/* end scope of else case */


}

/* end scope of foo */


}

October, 2nd 2009 Marcus Völp 48


Storage and Object Lifetime

Dynamic storage
• dynamically created objects

C* c = new C();

new[]

• lives until delete c; / delete[]

October, 2nd 2009 Marcus Völp 49


Guards <lock guard.cc>

• Problem:
Guarantee that a function is invoked on a long living object before the scope is
exited. E.g., release lock

• Objects with automatic storage location are destroyed when the scope is exited

class Lock {
void acquire();
void release();
}

class Lock_Guard { void foo {


Lock& _lock; int x;

Lock_Guard(Lock& lock); Lock_Guard guard = Lock_Guard(&cpu_lock);


~Lock_Guard(); do {
} ...
if (...) return;
Lock_Guard::Lock_Guard() while (...) {
: _lock(lock) { ... break;
_lock.acquire(); } while (true);
} }

Lock_Guard::~Lock_Guard() {
_lock.release();
}
October, 2nd 2009 Marcus Völp 50
The End

(for today)

October, 2nd 2009 Marcus Völp 51


Ringbuffer

• List:
+ size can be dynamic
+ co-location of list elements and large objects
+ sort without copying the object
- sort requires many queue operations
- allocation and deallocation overhead
- memory overhead for pointers

• often:
– FIFO of small elements
– Number of elements are known a-priori

head tail

October, 2nd 2009 Marcus Völp 52


Trees

• Binary tree / fixed number of children (example: page-tables)

• Tree with arbitrary many children (example: hierarchical names / directories)

• Common systems programming patterns:


– traverse tree only in a few directions (e.g., pre- / postorder)
e.g., delete directory only after children are gone => postorder

1 0 1 2 2 1
2

October, 2nd 2009 Marcus Völp 53

You might also like