diff --git a/20210128/aufgabe-1.c b/20210128/aufgabe-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb09b0e10aade5c202ed88fddcb2e52d700d9915
--- /dev/null
+++ b/20210128/aufgabe-1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdint.h>
+
+typedef struct
+{
+  uint32_t a;
+  uint64_t b;
+  uint8_t c;
+} three_numbers;
+
+int main (void)
+{
+  three_numbers xyz = { 1819042120, 2410670883059281007, 0 };
+  printf ("%s\n", &xyz);
+  return 0;
+}
diff --git a/20210128/aufgabe-2.c b/20210128/aufgabe-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..47595ef0658e94d76a42263e82200f94895cdeea
--- /dev/null
+++ b/20210128/aufgabe-2.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <string.h>
+
+typedef struct
+{
+  char first_name[10];
+  char family_name[20];
+  char day, month;
+  int year;
+} person;
+
+int main (void)
+{
+  person sls;
+  sls.day = 26;
+  sls.month = 7;
+  sls.year = 1951;
+  strcpy (sls.first_name, "Sabine");
+  strcpy (sls.family_name, "Leutheusser-Schnarrenberger");
+  printf ("%s %s wurde am %d.%d.%d geboren.\n",
+          sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+  return 0;
+}
diff --git a/20210128/aufgabe-3a.c b/20210128/aufgabe-3a.c
new file mode 100644
index 0000000000000000000000000000000000000000..61b6e79400afbb8ac0609eb1b72c04b83a0fce41
--- /dev/null
+++ b/20210128/aufgabe-3a.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  a[0]->wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  a[1]->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20210128/aufgabe-3b.c b/20210128/aufgabe-3b.c
new file mode 100644
index 0000000000000000000000000000000000000000..2cf3b56f4540f399d3761b0de929d80a1f1de611
--- /dev/null
+++ b/20210128/aufgabe-3b.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  ((with_wings *) a[0])->wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  ((with_legs *) a[1])->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20210128/hello-gtk.png b/20210128/hello-gtk.png
new file mode 120000
index 0000000000000000000000000000000000000000..cca99209d86683a9a3b0f70bbc149780bae10ba6
--- /dev/null
+++ b/20210128/hello-gtk.png
@@ -0,0 +1 @@
+../common/hello-gtk.png
\ No newline at end of file
diff --git a/20210128/hp-20210128.pdf b/20210128/hp-20210128.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..06019da71ff58c18d777f5090b46f6a469ebf29e
Binary files /dev/null and b/20210128/hp-20210128.pdf differ
diff --git a/20210128/hp-20210128.tex b/20210128/hp-20210128.tex
new file mode 100644
index 0000000000000000000000000000000000000000..b5e2211a60e816e0459c7e1d5130e716f0e66cc3
--- /dev/null
+++ b/20210128/hp-20210128.tex
@@ -0,0 +1,1404 @@
+% hp-20210128.pdf - Lecture Slides on Low-Level Programming
+% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Objektorientierte Programmierung
+
+\documentclass[10pt,t]{beamer}
+
+\usepackage{pgslides}
+\usepackage{rotating}
+\usepackage{tikz}
+
+\title{Hardwarenahe Programmierung}
+\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
+\date{28.\ Januar 2021}
+
+\begin{document}
+
+\maketitleframe
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Algorithmen}
+    \item[\textbf{5}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \item[5.1] Bit-Operationen
+        \item[5.2] I/O-Ports
+        \color{medgreen}
+        \item[5.3] Interrupts
+        \item[5.4] volatile-Variable
+        \item[5.6] Byte-Reihenfolge -- Endianness
+        \item[5.7] Binärdarstellung negativer Zahlen
+        \item[5.8] Speicherausrichtung -- Alignment
+      \end{itemize}
+    \item[\textbf{6}] \textbf{Objektorientierte Programmierung}
+      \begin{itemize}
+        \color{red}
+        \item[6.0] Dynamische Speicherverwaltung
+        \item[6.1] Konzepte und Ziele
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+%        \item[6.2] Beispiel: Zahlen und Buchstaben
+%        \color{red}
+%        \item[6.3] Unions
+%        \item[6.4] Virtuelle Methoden
+%        \color{black}
+%        \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI)
+%        \item[6.6] Ausblick: C++
+      \end{itemize}
+    \item[\textbf{7}] \textbf{Datenstrukturen}
+    \vspace*{-1cm}
+  \end{itemize}
+
+\end{frame}
+
+\setcounter{section}{4}
+\section{Hardwarenahe Programmierung}
+\subsection{Bit-Operationen}
+\subsubsection{Zahlensysteme}
+
+\begin{frame}[fragile]
+
+  \showsubsubsection
+
+  \begin{tabular}{rlrlrc}
+    \qquad 000 & \bf 0 \hspace*{1.5cm} & 0000 & \bf 0 & \quad 1000 & \bf 8\\
+           001 & \bf 1                 & 0001 & \bf 1 &       1001 & \bf 9\\
+           010 & \bf 2                 & 0010 & \bf 2 &       1010 & \bf A\\
+           011 & \bf 3                 & 0011 & \bf 3 &       1011 & \bf B\\[\smallskipamount]
+           100 & \bf 4                 & 0100 & \bf 4 &       1100 & \bf C\\
+           101 & \bf 5                 & 0101 & \bf 5 &       1101 & \bf D\\
+           110 & \bf 6                 & 0110 & \bf 6 &       1110 & \bf E\\
+           111 & \bf 7                 & 0111 & \bf 7 &       1111 & \bf F\\
+  \end{tabular}
+
+  \medskip
+
+  \begin{itemize}
+    \item
+      Oktal- und Hexadezimalzahlen lassen sich ziffernweise\\
+      in Binär-Zahlen umrechnen.
+    \item
+      Hexadezimalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
+      gruppiert zu jeweils 4 Bits.
+    \item
+      Oktalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
+      gruppiert zu jeweils 3 Bits.
+    \item
+      Trotz Taschenrechner u.\,ä.\ lohnt es sich,\\
+      die o.\,a.\ Umrechnungstabelle \textbf{auswendig} zu kennen.
+  \end{itemize}
+
+\end{frame}
+
+\subsubsection{Bit-Operationen in C}
+
+\begin{frame}[fragile]
+
+  \showsubsubsection
+
+  \begin{tabular}{lll}
+    C-Operator     & Verknüpfung              & Anwendung                \\[\smallskipamount]
+    \lstinline,&,  & Und                      & Bits gezielt löschen     \\
+    \lstinline,|,  & Oder                     & Bits gezielt setzen      \\
+    \lstinline,^,  & Exklusiv-Oder            & Bits gezielt invertieren \\
+    \lstinline,~,  & Nicht                    & Alle Bits invertieren    \\[\smallskipamount]
+    \lstinline,<<, & Verschiebung nach links  & Maske generieren         \\
+    \lstinline,>>, & Verschiebung nach rechts & Bits isolieren
+  \end{tabular}
+
+  \bigskip
+
+  Numerierung der Bits: von rechts ab 0
+
+  \medskip
+
+  \begin{tabular}{ll}
+    Bit Nr.\ 3 auf 1 setzen: &
+    \lstinline,a |= 1 << 3;, \\
+    Bit Nr.\ 4 auf 0 setzen: &
+    \lstinline,a &= ~(1 << 4);, \\
+    Bit Nr.\ 0 invertieren: &
+    \lstinline,a ^= 1 << 0;,
+  \end{tabular}
+
+  \smallskip
+
+  ~~Abfrage, ob Bit Nr.\ 1 gesetzt ist:\quad
+  \lstinline{if (a & (1 << 1))}
+
+\end{frame}
+
+\nosectionnonumber{Aufgabe}
+
+\begin{frame}[fragile]
+
+  \shownosectionnonumber
+
+  Schreiben Sie C-Funktionen, die ein "`Array von Bits"' realisieren, z.\,B.
+
+  \smallskip
+
+  \begin{tabular}[t]{ll}
+    \lstinline|void set_bit (int i);|   & Bei Index $i$ auf 1 setzen \\
+    \lstinline|void clear_bit (int i);| & Bei Index $i$ auf 0 setzen \\
+    \lstinline|int get_bit (int i);|    & Bei Index $i$ lesen
+  \end{tabular}
+
+  \medskip
+
+  Hinweise:
+  \begin{itemize}
+    \item
+      Die Größe des Bit-"`Arrays"' (z.\,B.\ 1000) dürfen Sie als \emph{vorher bekannt\/} voraussetzen.
+    \item
+      Sie benötigen ein Array, z.\,B.\ von \lstinline|char|- oder \lstinline|int|-Variablen.
+    \item
+      Sie benötigen eine Division (\lstinline|/|) sowie den Divisionsrest (Modulo: \lstinline|%|).
+  \end{itemize}
+
+  \bigskip
+
+  Diese Aufgabe berührt die Themen
+  "`Umgang mit Arrays und Zeigern"', "`Bit-Manipulation"'
+  und je nach Implementierung auch "`objektorientierte Programmierung"'.
+  Dies zu begründen, ist Teil der Aufgabe.
+
+\end{frame}
+
+\addtocounter{subsection}{1}
+
+\subsection{Interrupts}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: eingebaute Uhr\hfill
+  \makebox(0,0)[tr]{%
+    \only<1->{\begin{minipage}[t]{4.7cm}
+        \vspace*{-0.3cm}%
+        statt Zählschleife (\lstinline{_delay_ms}):\\
+        Hauptprogramm kann\\
+        andere Dinge tun
+      \end{minipage}}%
+    }
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/interrupt.h>
+
+    ...
+
+
+    ISR (TIMER0B_COMP_vect)
+    {
+      PORTD ^= 0x40;
+    }
+  \end{lstlisting}
+  \begin{picture}(0,0)
+    \color{red}
+    \put(1.9,3.1){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-1.4,-1.0);}}}
+    \put(2.0,3.2){\makebox(0,0)[l]{"`Dies ist ein Interrupt-Handler."'}}
+    \put(2.3,2.6){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.55);}}}
+    \put(2.4,2.6){\makebox(0,0)[l]{Interrupt-Vektor darauf zeigen lassen}}
+  \end{picture}
+
+  Initialisierung über spezielle Ports:
+  \lstinline{TCCR0B}, \lstinline{TIMSK0}
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+
+  \vspace*{-2.5cm}\hfill
+  {\color{red}Herstellerspezifisch!}%
+  \hspace*{1cm}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: Taster\hfill
+  \makebox(0,0)[tr]{%
+    \begin{minipage}[t]{4.7cm}
+      \vspace*{-0.3cm}%
+      statt \newterm{Busy Waiting\/}:\\
+      Hauptprogramm kann\\
+      andere Dinge tun
+    \end{minipage}}
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/interrupt.h>
+    ...
+
+    ISR (INT0_vect)
+    {
+      PORTD ^= 0x40;
+    }
+  \end{lstlisting}
+
+  \medskip
+
+  Initialisierung über spezielle Ports:
+  \lstinline{EICRA}, \lstinline{EIMSK}
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+
+  \vspace*{-2.5cm}\hfill
+  {\color{red}Herstellerspezifisch!}%
+  \hspace*{1cm}
+
+\end{frame}
+
+\subsection{volatile-Variable}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: Taster
+
+  \vspace*{-2.5pt}
+
+  \begin{minipage}[t]{5cm}
+    \begin{onlyenv}<1>
+      \begin{lstlisting}[gobble=8]
+        ¡#include <avr/interrupt.h>
+        ...
+
+        uint8_t key_pressed = 0;
+
+        ISR (INT0_vect)
+        {
+          key_pressed = 1;
+        }¿
+      \end{lstlisting}
+    \end{onlyenv}
+    \begin{onlyenv}<2>
+      \begin{lstlisting}[gobble=8]
+        ¡#include <avr/interrupt.h>
+        ...
+
+        volatile uint8_t key_pressed = 0;
+
+        ISR (INT0_vect)
+        {
+          key_pressed = 1;
+        }¿
+      \end{lstlisting}
+    \end{onlyenv}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{6cm}
+    \begin{lstlisting}[gobble=6]
+      ¡int main (void)
+      {
+        ...
+
+        while (1)
+          {
+            while (!key_pressed)
+              ;  /* just wait */
+            PORTD ^= 0x40;
+            key_pressed = 0;
+          }
+        return 0;
+      }¿
+    \end{lstlisting}
+  \end{minipage}
+
+  \pause
+  \begin{picture}(0,0)
+    \color{red}
+    \put(10.3,4.0){\makebox(0,0)[b]{\begin{minipage}{6cm}
+        \begin{center}
+          \textbf{volatile}:\\
+          Speicherzugriff\\
+          nicht wegoptimieren
+        \end{center}
+      \end{minipage}}}
+    \put(10.3,3.95){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.5,-0.9);}}}
+  \end{picture}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Was ist eigentlich \lstinline{PORTD}?
+
+  \bigskip
+%  \pause
+
+  \lstinline[style=cmd]{avr-gcc -Wall -Os -mmcu=atmega328p blink-3.c -E}
+
+  \bigskip
+%  \pause
+  \lstinline{PORTD = 0x01;}\\
+  \textarrow\quad
+  \lstinline[style=terminal]{(*(volatile uint8_t *)((0x0B) + 0x20)) = 0x01;}\\
+%  \pause
+  \begin{picture}(0,2)(0,-1.7)
+    \color{red}
+    \put(5.75,0.3){$\underbrace{\rule{2.95cm}{0pt}}_{\mbox{Zahl: \lstinline|0x2B|}}$}
+%    \pause
+    \put(1.55,0.3){$\underbrace{\rule{4.0cm}{0pt}}_{\mbox{\shortstack[t]{Umwandlung in Zeiger\\
+      auf \lstinline|volatile uint8_t|}}}$}
+%    \pause
+    \put(1.32,-1){\makebox(0,0)[b]{\tikz{\draw[-latex](0,0)--(0,1.3)}}}
+    \put(1.12,-1.1){\makebox(0,0)[tl]{Dereferenzierung des Zeigers}}
+  \end{picture}
+
+%  \pause
+  \textarrow\quad
+  \lstinline|volatile uint8_t|-Variable an Speicheradresse \lstinline|0x2B|
+
+%  \pause
+  \bigskip
+  \bigskip
+
+  \textarrow\quad
+  \lstinline|PORTA = PORTB = PORTC = PORTD = 0| ist eine schlechte Idee.
+
+\end{frame}
+
+\subsection{Byte-Reihenfolge -- Endianness}
+\subsubsection{Konzept}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+  \showsubsubsection
+
+  Eine Zahl geht über mehrere Speicherzellen.\\
+  Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen
+
+  \smallskip
+
+  Welche Bits liegen wo?
+
+%  \pause
+  \bigskip
+
+  $1027 = 1024 + 2 + 1 = 0000\,0100\,0000\,0011_2 = 0403_{16}$
+
+%  \pause
+  \bigskip
+  Speicherzellen:
+
+  \medskip
+  \begin{tabular}{|c|c|l}\cline{1-2}
+    \raisebox{-0.25ex}{04} & \raisebox{-0.25ex}{03} & \strut Big-Endian "`großes Ende zuerst"' \\\cline{1-2}
+    \multicolumn{2}{c}{} & für Menschen leichter lesbar \\
+    \multicolumn{3}{c}{} \\[-5pt]\cline{1-2}
+    \raisebox{-0.25ex}{03} & \raisebox{-0.25ex}{04} & \strut Little-Endian "`kleines Ende zuerst"' \\\cline{1-2}
+    \multicolumn{2}{c}{} & bei Additionen effizienter
+  \end{tabular}
+
+%  \pause
+  \medskip
+  \textarrow\ Geschmackssache
+%  \pause\\
+  \quad\textbf{\dots\ außer bei Datenaustausch!}
+
+%  \pause
+%  \bigskip
+%
+%  Aber: nicht verwechseln! \qquad $0304_{16} = 772$
+
+\end{frame}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  Eine Zahl geht über mehrere Speicherzellen.\\
+  Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen
+
+  \smallskip
+
+  Welche Bits liegen wo?
+
+  \medskip
+
+  \textarrow\ Geschmackssache\\
+  \textbf{\dots\ außer bei Datenaustausch!}
+
+  \begin{itemize}
+    \item
+      Dateiformate
+    \item
+      Datenübertragung
+  \end{itemize}
+
+\end{frame}
+
+\subsubsection{Dateiformate}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  Audio-Formate: Reihenfolge der Bytes in 16- und 32-Bit-Zahlen
+  \begin{itemize}
+    \item
+      RIFF-WAVE-Dateien (\file{.wav}): Little-Endian
+    \item
+      Au-Dateien (\file{.au}): Big-Endian
+%    \pause
+    \item
+      ältere AIFF-Dateien (\file{.aiff}): Big-Endian
+    \item
+      neuere AIFF-Dateien (\file{.aiff}): Little-Endian
+  \end{itemize}
+
+%  \pause
+  \bigskip
+
+  Grafik-Formate: Reihenfolge der Bits in den Bytes
+  \begin{itemize}
+    \item
+      PBM-Dateien: Big-Endian\only<1->{, MSB first}
+    \item
+      XBM-Dateien: Little-Endian\only<1->{, LSB first}
+  \end{itemize}
+  \only<1->{MSB/LSB = most/least significant bit}
+
+  \smallskip
+
+  Verwechselungsgefahr: most/least significant byte
+
+\end{frame}
+
+\subsubsection{Datenübertragung}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  \begin{itemize}
+    \item
+      RS-232 (serielle Schnittstelle): LSB first
+    \item
+      I$^2$C: MSB first
+    \item
+      USB: beides
+%    \pause
+    \medskip
+    \item
+      Ethernet: LSB first
+    \item
+      TCP/IP (Internet): Big-Endian
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Binärdarstellung negativer Zahlen}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Speicher ist begrenzt!\\
+  \textarrow\ feste Anzahl von Bits
+
+  \medskip
+
+  8-Bit-Zahlen ohne Vorzeichen: \lstinline{uint8_t}\\
+  \textarrow\ Zahlenwerte von \lstinline{0x00} bis \lstinline{0xff} = 0 bis 255\\
+%  \pause
+  \textarrow\ 255 + 1 = 0
+
+%  \pause
+  \medskip
+
+  8-Bit-Zahlen mit Vorzeichen: \lstinline{int8_t}\\
+  \lstinline{0xff} = 255 ist die "`natürliche"' Schreibweise für $-1$.\\
+%  \pause
+  \textarrow\ Zweierkomplement
+
+%  \pause
+  \medskip
+
+  Oberstes Bit = 1: negativ\\
+  Oberstes Bit = 0: positiv\\
+  \textarrow\ 127 + 1 = $-128$
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Speicher ist begrenzt!\\
+  \textarrow\ feste Anzahl von Bits
+
+  \medskip
+
+  16-Bit-Zahlen ohne Vorzeichen:
+  \lstinline{uint16_t}\hfill\lstinline{uint8_t}\\
+  \textarrow\ Zahlenwerte von \lstinline{0x0000} bis \lstinline{0xffff}
+  = 0 bis 65535\hfill 0 bis 255\\
+  \textarrow\ 65535 + 1 = 0\hfill 255 + 1 = 0
+
+  \medskip
+
+  16-Bit-Zahlen mit Vorzeichen:
+  \lstinline{int16_t}\hfill\lstinline{int8_t}\\
+  \lstinline{0xffff} = 66535 ist die "`natürliche"' Schreibweise für $-1$.\hfill
+  \lstinline{0xff} = 255 = $-1$\\
+  \textarrow\ Zweierkomplement
+
+  \medskip
+
+  Oberstes Bit = 1: negativ\\
+  Oberstes Bit = 0: positiv\\
+  \textarrow\ 32767 + 1 = $-32768$
+
+  \bigskip
+  Literatur: \url{http://xkcd.com/571/}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Frage: \emph{Für welche Zahl steht der Speicherinhalt\,
+  \raisebox{2pt}{%
+    \tabcolsep0.25em
+    \begin{tabular}{|c|c|}\hline
+      \rule{0pt}{11pt}a3 & 90 \\\hline
+    \end{tabular}}
+  (hexadezimal)?}
+  
+%  \pause
+  \smallskip
+  Antwort: \emph{Das kommt darauf an.} ;--)
+
+%  \pause
+  \medskip
+  Little-Endian:
+
+  \smallskip
+
+  \begin{tabular}{lrl}
+    als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\
+    als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\
+    als \lstinline,int16_t,: & $-28509$\\
+    als \lstinline,uint16_t,: & $37027$\\
+    \lstinline,int32_t, oder größer: & $37027$
+      & (zusätzliche Bytes mit Nullen aufgefüllt)
+  \end{tabular}
+
+%  \pause
+  \medskip
+  Big-Endian:
+
+  \smallskip
+
+  \begin{tabular}{lrl}
+    als \lstinline,int8_t,:   & $-93$ & (nur erstes Byte)\\
+    als \lstinline,uint8_t,:  & $163$ & (nur erstes Byte)\\
+    als \lstinline,int16_t,:  & $-23664$\\
+    als \lstinline,uint16_t,: & $41872$\\ als \lstinline,int32_t,:  & $-1550843904$ & (zusätzliche Bytes\\
+    als \lstinline,uint32_t,: & $2744123392$  & mit Nullen aufgefüllt)\\
+    als \lstinline,int64_t,:  & $-6660823848880963584$\\
+    als \lstinline,uint64_t,: & $11785920224828588032$\\
+  \end{tabular}
+
+  \vspace*{-1cm}
+
+\end{frame}
+
+\subsection{Speicherausrichtung -- Alignment}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \begin{lstlisting}
+    #include <stdint.h>
+
+    uint8_t a;
+    uint16_t b;
+    uint8_t c;
+  \end{lstlisting}
+
+%  \pause
+  \bigskip
+
+  Speicheradresse durch 2 teilbar -- "`16-Bit-Alignment"'
+  \begin{itemize}
+    \item
+      2-Byte-Operation: effizienter
+%    \pause
+    \item
+      \dots\ oder sogar nur dann erlaubt
+%    \pause
+    \arrowitem
+      Compiler optimiert Speicherausrichtung
+  \end{itemize}
+
+  \medskip
+
+%  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t dummy;
+      uint16_t b;
+      uint8_t c;¿
+    \end{lstlisting}
+  \end{minipage}
+%  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t c;
+      uint16_t b;¿
+    \end{lstlisting}
+  \end{minipage}
+
+%  \pause
+  \vspace{-1.75cm}
+  \strut\hfill
+  \begin{minipage}{6.5cm}
+    Fazit:
+    \begin{itemize}
+      \item
+        \textbf{Adressen von Variablen\\
+        sind systemabhängig}
+      \item
+        Bei Definition von Datenformaten\\
+        Alignment beachten \textarrow\ effizienter
+    \end{itemize}
+  \end{minipage}
+
+\end{frame}
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Algorithmen}
+    \item[\textbf{5}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \item[5.1] Bit-Operationen
+        \item[5.2] I/O-Ports
+        \color{medgreen}
+        \item[5.3] Interrupts
+        \item[5.4] volatile-Variable
+        \item[5.6] Byte-Reihenfolge -- Endianness
+        \item[5.7] Binärdarstellung negativer Zahlen
+        \item[5.8] Speicherausrichtung -- Alignment
+      \end{itemize}
+    \item[\textbf{6}] \textbf{Objektorientierte Programmierung}
+      \begin{itemize}
+        \color{red}
+        \item[6.0] Dynamische Speicherverwaltung
+        \item[6.1] Konzepte und Ziele
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+%        \item[6.2] Beispiel: Zahlen und Buchstaben
+%        \color{red}
+%        \item[6.3] Unions
+%        \item[6.4] Virtuelle Methoden
+%        \color{black}
+%        \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI)
+%        \item[6.6] Ausblick: C++
+      \end{itemize}
+    \item[\textbf{7}] \textbf{Datenstrukturen}
+    \vspace*{-1cm}
+  \end{itemize}
+
+\end{frame}
+
+\section{Objektorientierte Programmierung}
+
+\addtocounter{subsection}{-1}
+\subsection{Dynamische Speicherverwaltung}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen)
+    \item
+      Dynamisches Array: variable Anzahl von Elementen desselben Typs
+  \end{itemize}
+
+  \bigskip
+
+  \begin{lstlisting}
+    char *name[] = { "Anna", "Berthold", "Caesar" };
+
+    ...
+
+     name[3] = "Dieter";
+  \end{lstlisting}
+
+  \begin{picture}(0,0)
+    \color{red}
+    \put(0,0){\line(3,1){3.5}}
+    \put(0,1){\line(3,-1){3.5}}
+  \end{picture}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \bigskip
+
+  \begin{lstlisting}
+    #include <stdlib.h>
+
+    ...
+
+      char **name = malloc (3 * sizeof (char *));
+        /* Speicherplatz für 3 Zeiger anfordern */
+
+    ...
+
+      free (name)
+        /* Speicherplatz freigeben */
+
+  \end{lstlisting}
+
+\end{frame}
+
+\subsection{Konzepte und Ziele}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+%      Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen)
+      Array: Elemente desselben Typs (z.\,B.\ 3 ganze Zahlen)
+%    \item
+%      Dynamisches Array: variable Anzahl von Elementen desselben Typs
+    \item
+      Problem: Elemente unterschiedlichen Typs
+    \item
+      Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt}
+    \item
+      Problem: Die Elemente sind unterschiedlich groß (Speicherplatz).
+    \item
+      Lösung: Im Array nicht die Objekte selbst speichern, sondern Zeiger darauf.
+  \end{itemize}
+  \begin{itemize}
+    \item
+      Funktionen, die mit dem Objekt arbeiten: \newterm{Methoden}
+    \begin{onlyenv}<1>
+      \item
+        Was die Funktion bewirkt,\\
+        hängt vom Typ des Objekts ab
+      \item
+        Realisierung über endlose \lstinline{if}-Ketten
+    \end{onlyenv}
+    \begin{onlyenv}<2>
+      \item
+        Was die Funktion bewirkt
+        \begin{picture}(0,0)
+          \color{red}
+          \put(-4.00,-0.05){\tikz{\draw[thick](0,0.25)--(3.75,-0.05);%
+                                  \draw[thick](-0.1,-0.05)--(3.75,0.3);}}
+        \end{picture}%
+        Welche Funktion aufgerufen wird,\\
+        hängt vom Typ des Objekts ab: \newterm{virtuelle Methode}
+      \item
+        Realisierung über endlose \lstinline{if}-Ketten%
+        \begin{picture}(0,0)
+          \color{red}
+          \put(-2.75,-0.05){\tikz{\draw[thick](0,0.25)--(2.5,-0.05);%
+                                  \draw[thick](-0.1,-0.05)--(2.5,0.3);}}
+          \put(1.5,-1.1){\begin{rotate}{7}\large\bf\textarrow\
+                           kommt gleich
+%                           nächste Woche
+                         \end{rotate}}
+        \end{picture}
+        Zeiger, die im Objekt gespeichert sind\\
+        (Genaugenommen: Tabelle von Zeigern)
+    \end{onlyenv}
+  \end{itemize}
+
+\end{frame}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Problem: Elemente unterschiedlichen Typs
+    \item
+      Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt}
+    \item
+      \newterm{Methoden\/} und \newterm{virtuelle Methoden}
+  \end{itemize}
+
+  \begin{itemize}
+    \item
+      Zeiger auf verschiedene Strukturen\\
+      mit einem gemeinsamen Anteil von Datenfeldern\\
+      \textarrow\ "`verwandte"' \newterm{Objekte}, \newterm{Klassen} von Objekten
+    \item
+      Struktur, die \emph{nur\/} den gemeinsamen Anteil enthält\\
+      \textarrow\ "`Vorfahr"', \newterm{Basisklasse}, \newterm{Vererbung}
+    \item
+%      Explizite Typumwandlung eines Zeigers auf die Basisklasse\\
+%      in einen Zeiger auf die \newterm{abgeleitete Klasse}\\
+%      \textarrow\ Man kann ein Array unterschiedlicher Objekte\\
+%      \strut\phantom{\textarrow} in einer Schleife abarbeiten.\\
+      Zeiger auf die Basisklasse dürfen auf Objekte\\
+      der \newterm{abgeleiteten Klasse} zeigen\\
+      \textarrow\ \newterm{Polymorphie}
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Beispiel: Zahlen und Buchstaben}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \begin{center}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+        } t_base;¿
+      \end{lstlisting}
+    \end{minipage}\\[0.5cm]
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+          int content;
+        } t_integer;¿
+      \end{lstlisting}
+    \end{minipage}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+          char *content;
+        } t_string;¿
+      \end{lstlisting}
+    \end{minipage}
+  \end{center}
+  
+\end{frame}
+
+\begin{frame}[fragile]
+  \begin{center}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+        } t_base;¿
+      \end{lstlisting}
+    \end{minipage}\\[0.5cm]
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+          int content;
+        } t_integer;¿
+      \end{lstlisting}
+    \end{minipage}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          int type;
+          char *content;
+        } t_string;¿
+      \end{lstlisting}
+    \end{minipage}\\[0.7cm]
+    \begin{onlyenv}<1>
+      \begin{minipage}{8cm}
+        \begin{lstlisting}[gobble=10]
+          ¡t_integer i = { 1, 42 };
+          t_string s = { 2, "Hello, world!" };
+
+          t_base *object[] = { (t_base *) &i, (t_base *) &s };¿
+        \end{lstlisting}
+      \end{minipage}%
+      \begin{picture}(0,0)
+        \color{red}
+        \put(-5.4,-0.8){\mbox{$\underbrace{\rule{1.45cm}{0pt}}_{\shortstack{\strut explizite\\Typumwandlung}}$}}
+      \end{picture}
+    \end{onlyenv}
+%    \begin{onlyenv}<2>
+%      \begin{minipage}{5cm}
+%        \begin{lstlisting}[gobble=10]
+%          ¡typedef union
+%          {
+%            t_base base;
+%            t_integer integer;
+%            t_string string;
+%          } t_object;¿
+%        \end{lstlisting}
+%      \end{minipage}
+%    \end{onlyenv}
+  \end{center}
+  
+\end{frame}
+
+\subsection{Unions}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Variable teilen sich denselben Speicherplatz.
+
+  \medskip
+
+  \begin{minipage}[t]{3.7cm}
+    \begin{lstlisting}[gobble=6]
+      ¡typedef union
+      {
+        int8_t i;
+        uint8_t u;
+      } num8_t;¿
+    \end{lstlisting}
+  \end{minipage}%
+  \begin{minipage}[t]{4.5cm}
+    \begin{lstlisting}[gobble=6]
+      ¡int main (void)
+      {
+        num8_t test;
+        test.i = -1;
+        printf ("%d\n", test.u);
+        return 0;
+      }¿
+    \end{lstlisting}
+  \end{minipage}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Variable teilen sich denselben Speicherplatz.
+
+  \medskip
+
+  \begin{minipage}[t]{3.7cm}
+    \begin{lstlisting}[gobble=6]
+      ¡typedef union
+      {
+        char s[8];
+        uint64_t x;
+      } num_char_t;¿
+    \end{lstlisting}
+  \end{minipage}%
+  \begin{minipage}[t]{4.5cm}
+    \begin{lstlisting}[gobble=6]
+      ¡int main (void)
+      {
+        num_char_t test = { "Hello!" };
+        printf ("%lx\n", test.x);
+        return 0;
+      }¿
+    \end{lstlisting}
+  \end{minipage}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Variable teilen sich denselben Speicherplatz.
+
+  \medskip
+
+  \begin{minipage}[t]{3.7cm}
+    \begin{lstlisting}[gobble=6]
+      ¡typedef union
+      {
+        t_base base;
+        t_integer integer;
+        t_string string;
+      } t_object;¿
+    \end{lstlisting}
+  \end{minipage}%
+  \begin{minipage}[t]{3.0cm}
+    \begin{lstlisting}[gobble=6]
+
+      ¡typedef struct
+      {
+        int type;
+      } t_base;¿
+    \end{lstlisting}
+  \end{minipage}%
+  \begin{minipage}[t]{3.0cm}
+    \begin{lstlisting}[gobble=6]
+
+      ¡typedef struct
+      {
+        int type;
+        int content;
+      } t_integer;¿
+    \end{lstlisting}
+  \end{minipage}%
+  \begin{minipage}[t]{3.0cm}
+    \begin{lstlisting}[gobble=6]
+
+      ¡typedef struct
+      {
+        int type;
+        char *content;
+      } t_string;¿
+    \end{lstlisting}
+  \end{minipage}
+
+  \bigskip
+
+  \begin{center}
+    \begin{minipage}{8.5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡if (this->base.type == T_INTEGER)
+          printf ("Integer: %d\n", this->integer.content);
+        else if (this->base.type == T_STRING)
+          printf ("String: \"%s\"\n", this->string.content);¿
+      \end{lstlisting}
+    \end{minipage}
+  \end{center}
+
+\end{frame}
+
+\subsection{Virtuelle Methoden}
+
+\begin{frame}[fragile]
+  \showsubsection
+
+  \begin{lstlisting}
+    void print_object (t_object *this)
+    {
+      if (this->base.type == T_INTEGER)
+        printf ("Integer: %d\n", this->integer.content);
+      else if (this->base.type == T_STRING)
+        printf ("String: \"%s\"\n", this->string.content);
+    }
+  \end{lstlisting}
+
+  \begin{picture}(0,0)
+    \color{red}
+    \put(9,1.7){\shortstack[l]{if-Kette:\\\strut wird unübersichtlich}}
+    \put(1,-2){\mbox{\textarrow}}
+    \put(0,-3){\mbox{Zeiger auf Funktionen}}
+  \end{picture}
+
+  \begin{lstlisting}[xleftmargin=4cm]
+    void print_integer (t_object *this)
+    {
+      printf ("Integer: %d\n", this->integer.content);
+    }
+
+    void print_string (t_object *this)
+    {
+      printf ("String: \"%s\"\n", this->string.content);
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\begin{frame}[fragile]
+  \showsubsection
+
+  Zeiger auf Funktionen
+
+  \medskip
+
+  \begin{lstlisting}
+    void (* print) (t_object *this);
+  \end{lstlisting}
+  \begin{picture}(0,1.2)(0,-0.9)
+    \color{red}
+    \put(0.95,0.3){\mbox{$\underbrace{\rule{1cm}{0pt}}$}}
+    \put(0.2,-0.7){\shortstack{das, worauf print zeigt,\\ist eine Funktion}}
+  \end{picture}
+
+  \begin{itemize}
+    \item
+      Objekt enthält Zeiger auf Funktion
+      \begin{onlyenv}<1>
+        \medskip
+        \begin{lstlisting}[gobble=10]
+          typedef struct
+          {
+            void (* print) (union t_object *this);
+            int content;
+          } t_integer;
+        \end{lstlisting}
+      \end{onlyenv}
+      \begin{onlyenv}<2->
+        \vspace*{-3.5cm}  % Why doesn't a picture environment work here??? :-(
+        \begin{lstlisting}[gobble=10,xleftmargin=5.5cm]
+          typedef struct
+          {
+            void (* print) (union t_object *this);
+            int content;
+          } t_integer;
+        \end{lstlisting}
+        \vspace*{0.85cm}
+        \bigskip
+        \smallskip
+      \end{onlyenv}
+    \pause
+    \item
+      Konstruktor initialisiert diesen Zeiger
+      \begin{onlyenv}<2>
+        \medskip
+        \begin{lstlisting}[gobble=10]
+          t_object *new_integer (int i)
+          {
+            t_object *p = malloc (sizeof (t_integer));
+            p->integer.print = print_integer;
+            p->integer.content = i;
+            return p;
+          }
+        \end{lstlisting}
+        \vspace*{-2cm}
+      \end{onlyenv}
+    \pause
+    \item
+      Aufruf: "`automatisch"' die richtige Funktion
+      \begin{onlyenv}<3>
+        \medskip
+        \begin{lstlisting}[gobble=10]
+          for (int i = 0; object[i]; i++)
+            object[i]->base.print (object[i]);
+        \end{lstlisting}
+      \end{onlyenv}
+    \pause
+    \medskip
+    \item
+      in größeren Projekten:\\
+      Objekt enthält Zeiger auf Tabelle von Funktionen
+  \end{itemize}
+\end{frame}
+
+\subsection{Beispiel: Graphische Benutzeroberfläche (GUI)}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \scriptsize
+  \begin{lstlisting}
+    #include <gtk/gtk.h>
+
+    int main (int argc, char **argv)
+    {
+      gtk_init (&argc, &argv);
+      GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_window_set_title (GTK_WINDOW (window), "Hello");
+      g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+      GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+      gtk_container_add (GTK_CONTAINER (window), vbox);
+      gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+      GtkWidget *label = gtk_label_new ("Hello, world!");
+      gtk_container_add (GTK_CONTAINER (vbox), label);
+      GtkWidget *button = gtk_button_new_with_label ("Quit");
+      g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+      gtk_container_add (GTK_CONTAINER (vbox), button);
+      gtk_widget_show (button);
+      gtk_widget_show (label);
+      gtk_widget_show (vbox);
+      gtk_widget_show (window);
+      gtk_main ();
+      return 0;
+    }
+  \end{lstlisting}
+
+  \vspace*{-6cm}\strut\hfill
+  \includegraphics[scale=0.85]{hello-gtk.png}\\[2cm]
+  \begin{flushright}
+    \normalsize\bf Praktikumsversuch:\\
+    Objektorientiertes Zeichenprogramm
+  \end{flushright}
+  
+\end{frame}
+
+\subsection{Ausblick: C++}
+
+\begin{frame}[fragile]
+  \showsubsection
+
+  \begin{center}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          void (* print) (union t_object *this);
+        } t_base;¿
+      \end{lstlisting}
+    \end{minipage}\\[0.5cm]
+    \begin{minipage}{5.5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          void (* print) (...);
+          int content;
+        } t_integer;¿
+      \end{lstlisting}
+    \end{minipage}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡typedef struct
+        {
+          void (* print) (union t_object *this);
+          char *content;
+        } t_string;¿
+      \end{lstlisting}
+    \end{minipage}
+  \end{center}
+  
+\end{frame}
+
+\begin{frame}[fragile]
+  \showsubsection
+
+  \begin{center}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡struct TBase
+        {
+          virtual void print (void);
+        };¿
+      \end{lstlisting}
+    \end{minipage}\\[0.5cm]
+    \begin{minipage}{5.5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡struct TInteger: public TBase
+        {
+          virtual void print (void);
+          int content;
+        };¿
+      \end{lstlisting}
+    \end{minipage}
+    \begin{minipage}{5cm}
+      \begin{lstlisting}[gobble=8]
+        ¡struct TString: public TBase
+        {
+          virtual void print (void);
+          char *content;
+        };¿
+      \end{lstlisting}
+    \end{minipage}
+  \end{center}
+  
+\end{frame}
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Algorithmen}
+    \item[\textbf{5}] \textbf{Hardwarenahe Programmierung}
+    \item[\textbf{6}] \textbf{Objektorientierte Programmierung}
+      \begin{itemize}
+        \color{medgreen}
+        \item[6.0] Dynamische Speicherverwaltung
+        \item[6.1] Konzepte und Ziele
+        \item[6.2] Beispiel: Zahlen und Buchstaben
+        \item[6.3] Unions
+        \item[6.4] Virtuelle Methoden
+        \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI)
+        \item[6.6] Ausblick: C++
+      \end{itemize}
+    \item[\textbf{7}] \textbf{Datenstrukturen}
+    \vspace*{-1cm}
+  \end{itemize}
+
+\end{frame}
+
+\end{document}
diff --git a/20210128/hp-musterloesung-20210128.pdf b/20210128/hp-musterloesung-20210128.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..05884e3ee698a07f1924d6b18f57a8c29c7374e9
Binary files /dev/null and b/20210128/hp-musterloesung-20210128.pdf differ
diff --git a/20210128/hp-musterloesung-20210128.tex b/20210128/hp-musterloesung-20210128.tex
new file mode 100644
index 0000000000000000000000000000000000000000..93131492c646f3186f1715c1f7e4bf4a1bb23b88
--- /dev/null
+++ b/20210128/hp-musterloesung-20210128.tex
@@ -0,0 +1,763 @@
+% hp-musterloesung-20210128.pdf - Solutions to the Exercises on Low-Level Programming
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Speicherformate von Zahlen, Personen-Datenbank, objektorientierte Tier-Datenbank
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- 28.\ Januar 2021}
+
+  \exercise{Speicherformate von Zahlen}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210128}{aufgabe-1.c}):
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <stdint.h>
+
+    typedef struct
+    {
+      uint32_t a;
+      uint64_t b;
+      uint8_t c;
+    } three_numbers;
+
+    int main (void)
+    {
+      three_numbers xyz = { 1819042120, 2410670883059281007, 0 };
+      printf ("%s\n", &xyz);
+      return 0;
+    }
+  \end{lstlisting}
+
+  Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\
+  (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür,
+  daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.)
+
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -Wall -m32 aufgabe-2.c -o aufgabe-2¿
+    aufgabe-2.c: In function "main":
+    aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", but
+    argument 2 has type "three_numbers * {aka struct <anonymous> *}" [-Wformat=]
+       printf ("%s\n", &xyz);
+                 ^
+    $ ¡./aufgabe-2¿
+    Hallo, Welt!
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie die beim Compilieren auftretende Warnung.
+      \points{2}
+    \item
+      Erklären Sie die Ausgabe des Programms.
+      \points{4}
+    \item
+      Welche Endianness hat der verwendete Rechner?
+      Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?
+      \points{2}
+    \item
+      Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\
+      (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür,
+      daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.)
+      \begin{lstlisting}[style=terminal,gobble=8]
+        $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿
+        aufgabe-2.c: In function "main":
+        aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *",
+        but argument 2 has type "three_numbers * {aka struct <anonymous> *}"
+        [-Wformat=]
+           printf ("%s\n", &xyz);
+                     ^
+        $ ¡./aufgabe-2¿
+        Hall5V
+      \end{lstlisting}
+      (Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)\par
+      Erklären Sie die geänderte Ausgabe des Programms.
+      \points{3}
+  \end{enumerate}
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Erklären Sie die beim Compilieren auftretende Warnung.}
+
+      Die Funktion \lstinline{printf()} mit der Formatspezifikation \lstinline{%s}
+      erwartet als Parameter einen String, d.\,h.\ einen Zeiger auf \lstinline{char}.
+      Die Adresse (\lstinline{&}) der Variablen \lstinline{xyz}
+      ist zwar ein Zeiger, aber nicht auf \lstinline{char},
+      sondern auf einen \lstinline{struct} vom Typ \lstinline{three_numbers}.
+      Eine implizite Umwandlung des Zeigertyps ist zwar möglich,
+      aber normalerweise nicht das, was man beabsichtigt.
+
+    \item
+      \textbf{Erklären Sie die Ausgabe des Programms.}
+
+      Ein String in C ist ein Array von \lstinline{char}s
+      bzw.\ ein Zeiger auf \lstinline{char}.
+      Da die Funktion \lstinline{printf()} mit der Formatspezifikation \lstinline{%s}
+      einen String erwartet, wird sie das, worauf der übergebene Zeiger zeigt,
+      als ein Array von \lstinline{char}s interpretieren.
+      Ein \lstinline{char} entspricht einer 8-Bit-Speicherzelle.
+      Um die Ausgabe des Programms zu erklären, müssen wir daher
+      die Speicherung der Zahlen in den einzelnen 8-Bit-Speicherzellen betrachten.
+
+      Hierfür wandeln wir zunächst die Zahlen von Dezimal nach Hexadezimal um.
+      Sofern nötig (hier nicht der Fall) füllen wir von links mit Nullen auf,
+      um den gesamten von der Variablen belegten Speicherplatz zu füllen
+      (hier: 32 Bit, 64 Bit, 8 Bit).
+      Jeweils 2 Hex-Ziffern stehen für 8 Bit.
+      \begin{center}
+        \begin{tabular}{rcl}
+          dezimal & & hexadezimal \\[\smallskipamount]
+          1\,819\,042\,120 & = & 6C\,6C\,61\,48 \\
+          2\,410\,670\,883\,059\,281\,007 & = & 21\,74\,6C\,65\,57\,20\,2C\,6F \\
+          0 & = & 00
+        \end{tabular}
+      \end{center}
+      Die Anordnung dieser 8-Bit-Zellen im Speicher lautet
+      \textbf{auf einem Big-Endian-Rechner} wie folgt:
+      \begin{center}
+        \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline
+          \raisebox{0.5ex}{\strut}
+            6C & 6C & 61 & 48 &
+            21 & 74 & 6C & 65 & 57 & 20 & 2C & 6F &
+            00
+          \\\hline
+        \end{tabular}\\[-4.2ex]
+        \kern1.7em%
+        $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt%
+        $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt%
+        $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$%
+      \end{center}
+      \textbf{Auf einem Little-Endian-Rechner} lautet sie hingegen:
+      \begin{center}
+        \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline
+%          \raisebox{0.5ex}{\strut}
+%            H & a & l & l &
+%            o & , &   & W & e & l & t & ! &  \\\hline
+          \raisebox{0.5ex}{\strut}
+            48 & 61 & 6C & 6C &
+            6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 &
+            00
+          \\\hline
+        \end{tabular}\\[-4.2ex]
+        \kern1.7em%
+        $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt%
+        $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt%
+        $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$%
+      \end{center}
+      Anhand einer ASCII-Tabelle erkennt man,
+      daß die Big-Endian-Variante dem String \lstinline{"llaH!tleW ,o"}
+      und die Little-Endian-Variante dem String \lstinline{"Hallo, Welt!"}
+      entspricht -- jeweils mit einem Null-Symbol am Ende,
+      das von der Variablen \lstinline{c} herrührt.
+
+      Auf einem Little-Endian-Rechner wird daher
+      \lstinline[style=terminal]{Hallo, Welt!} ausgegeben.
+
+    \item
+      \textbf{Welche Endianness hat der verwendete Rechner?}
+
+      Little-Endian (Begründung siehe oben)
+
+      \textbf{Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?}
+
+      \lstinline[style=terminal]{llaH!tleW ,o} (Begründung siehe oben)
+
+    \item
+      \textbf{Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\
+      (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür,
+      daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.)}
+      \begin{lstlisting}[style=terminal,gobble=8]
+        $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿
+        aufgabe-2.c: In function "main":
+        aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *",
+        but argument 2 has type "three_numbers * {aka struct <anonymous> *}"
+        [-Wformat=]
+           printf ("%s\n", &xyz);
+                     ^
+        $ ¡./aufgabe-2¿
+        Hall5V
+      \end{lstlisting}
+      \textbf{(Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)}\par
+      \textbf{Erklären Sie die geänderte Ausgabe des Programms.}
+
+      \goodbreak
+
+      Auf einem 64-Bit-Rechner hat eine 64-Bit-Variable
+      ein \textbf{64-Bit-Alignment},
+      d.\,h.\ ihre Speicheradresse muß durch 8 teilbar sein.
+
+      Der Compiler legt die Variablen daher wie folgt im Speicher ab (Little-Endian):
+      \begin{center}
+        \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline
+          \raisebox{0.5ex}{\strut}
+            48 & 61 & 6C & 6C & ?? & ?? & ?? & ?? &
+            6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 &
+            00
+          \\\hline
+        \end{tabular}\\[-4.2ex]
+        \kern1.7em%
+        $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt%
+        $\underbrace{\rule{9.1em}{0pt}}_{\mbox{Füll-Bytes}}$\kern1pt%
+        $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt%
+        $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$%
+      \end{center}
+      Der Inhalt der Füll-Bytes ist undefiniert.
+      Im Beispiel aus der Aufgabenstellung entsteht hier die Ausgabe
+      \lstinline[style=terminal]{5V}, was den (zufälligen) hexadezimalen Werten
+      35 56 entspricht:
+      \begin{center}
+        \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline
+          \raisebox{0.5ex}{\strut}
+            48 & 61 & 6C & 6C & 35 & 56 & 00 & ?? &
+            6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 &
+            00
+          \\\hline
+        \end{tabular}\\[-4.2ex]
+        \kern1.7em%
+        $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt%
+        $\underbrace{\rule{9.1em}{0pt}}_{\mbox{Füll-Bytes}}$\kern1pt%
+        $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt%
+        $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$%
+      \end{center}
+      Da danach die Ausgabe aufhört, muß an der nächsten Stelle
+      ein Null-Symbol stehen, das das Ende des Strings anzeigt.
+      Der Inhalt der darauf folgenden Speicherzelle bleibt unbekannt.
+  \end{enumerate}
+
+  \exercise{Personen-Datenbank}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210128}{aufgabe-2.c}):
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    typedef struct
+    {
+      char first_name[10];
+      char family_name[20];
+      char day, month;
+      int year;
+    } person;
+
+    int main (void)
+    {
+      person sls;
+      sls.day = 26;
+      sls.month = 7;
+      sls.year = 1951;
+      strcpy (sls.first_name, "Sabine");
+      strcpy (sls.family_name, "Leutheusser-Schnarrenberger");
+      printf ("%s %s wurde am %d.%d.%d geboren.\n",
+              sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+      return 0;
+    }
+  \end{lstlisting}
+
+  Die Standard-Funktion \lstinline{strcpy()} bewirkt ein Kopieren eines Strings
+  von rechts nach links, hier also z.\,B.\ die Zuweisung der String-Konstanten
+  \lstinline{"Sabine"} an die String-Variable \lstinline{sls.first_name[]}.
+
+  Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\
+  (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür,
+  daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.)
+
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -Wall -O -m32 aufgabe-2.c -o aufgabe-2¿
+    $ ¡./aufgabe-2¿
+    Sabine Leutheusser-Schnarrenberger wurde am 110.98.1701278309 geboren.
+    Speicherzugriffsfehler
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie die Ausgabe des Programms einschließlich der Zahlenwerte.
+      \points{4}
+    \item
+      Welche Endianness hat der verwendete Rechner?
+      Begründen Sie Ihre Antwort.
+      \points{1}
+    \item
+      Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?
+      \points{2}
+    \item
+      Erklären Sie den Speicherzugriffsfehler.
+      (Es kann sein, daß sich der Fehler auf Ihrem Rechner nicht bemerkbar macht.
+      Er ist aber trotzdem vorhanden.)
+      \points{2}
+  \end{enumerate}
+
+  \goodbreak
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Erklären Sie die Ausgabe des Programms einschließlich der Zahlenwerte.}
+
+      Der String \lstinline{"Leutheusser-Schnarrenberger"}
+      hat 27 Zeichen und daher mehr als die in der Variablen
+      \lstinline{sls.family_name} vorgesehenen 20 Zeichen.
+      Das \lstinline{"nberger"} paßt nicht mehr in die String-Variable.
+      
+      Die Zuweisung \lstinline{strcpy (sls.family_name, "Leutheusser-Schnarrenberger")}
+      überschreibt daher 8 Speicherzellen außerhalb der String-Variablen
+      \lstinline{sls.family_name} mit dem String \lstinline{"nberger"}
+      (7 Buchstaben zzgl.\ String-Ende-Symbol) -- und damit insbesondere die Variablen
+      \lstinline{sls.day}, \lstinline{sls.month} und \lstinline{sls.year}.
+
+      Die überschriebenen Speicherzellen sehen demnach folgendermaßen aus:
+      \begin{center}
+        \begin{picture}(8,1.5)(0,-0.5)
+          \put(0,0){\line(1,0){8}}
+          \put(0,1){\line(1,0){8}}
+          \multiput(0,0)(1,0){9}{\line(0,1){1}}
+          \put(0.4,0.38){\lstinline{n}}
+          \put(1.4,0.38){\lstinline{b}}
+          \put(2.4,0.38){\lstinline{e}}
+          \put(3.4,0.38){\lstinline{r}}
+          \put(4.4,0.38){\lstinline{g}}
+          \put(5.4,0.38){\lstinline{e}}
+          \put(6.4,0.38){\lstinline{r}}
+          \put(7.5,0.5){\makebox(0,0){\lstinline{0x00}}}
+          \put(0.5,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{0.95cm}{0pt}}_{\mbox{\lstinline{day}}}$}}
+          \put(1.5,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{0.95cm}{0pt}}_{\mbox{\lstinline{month}}}$}}
+          \put(4.0,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{3.95cm}{0pt}}_{\mbox{\lstinline{year}}}$}}
+          \put(7.0,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{1.95cm}{0pt}}_{\mbox{?}}$}}
+        \end{picture}
+      \end{center}
+      ("`?"' steht für zwei Speicherzellen, von denen wir nicht wissen,
+      wofür sie genutzt werden.)
+
+      Wenn wir die ASCII-Zeichen in Hexadezimalzahlen umrechnen, entspricht dies:
+      \begin{center}
+        \begin{picture}(7,1.5)(0,-0.5)
+          \put(0,0){\line(1,0){8}}
+          \put(0,1){\line(1,0){8}}
+          \multiput(0,0)(1,0){9}{\line(0,1){1}}
+          \put(0.5,0.5){\makebox(0,0){\lstinline{0x6e}}}
+          \put(1.5,0.5){\makebox(0,0){\lstinline{0x62}}}
+          \put(2.5,0.5){\makebox(0,0){\lstinline{0x65}}}
+          \put(3.5,0.5){\makebox(0,0){\lstinline{0x72}}}
+          \put(4.5,0.5){\makebox(0,0){\lstinline{0x67}}}
+          \put(5.5,0.5){\makebox(0,0){\lstinline{0x65}}}
+          \put(6.5,0.5){\makebox(0,0){\lstinline{0x72}}}
+          \put(7.5,0.5){\makebox(0,0){\lstinline{0x00}}}
+          \put(0.5,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{0.95cm}{0pt}}_{\mbox{\lstinline{day}}}$}}
+          \put(1.5,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{0.95cm}{0pt}}_{\mbox{\lstinline{month}}}$}}
+          \put(4.0,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{3.95cm}{0pt}}_{\mbox{\lstinline{year}}}$}}
+          \put(7.0,-0.1){\makebox(0,0)[t]{$\underbrace{\rule{1.95cm}{0pt}}_{\mbox{?}}$}}
+        \end{picture}
+      \end{center}
+      Dies entspricht bereits genau den Werten \lstinline{110} und \lstinline{98}
+      für die Variablen \lstinline{sls.day} bzw.\ \lstinline{sls.month}.
+
+      Für die Variable \lstinline{sls.year} müssen wir ihre vier Speicherzellen
+      unter der Berücksichtigung der Endianness des Rechners zusammenziehen.
+      Für Big-Endian ergibt dies \lstinline{0x65726765 == 1701996389}.
+      Für Little-Endian ergibt sich der Wert \lstinline{0x65677265 == 1701278309},
+      der auch in der Ausgabe des Programms auftaucht.
+
+    \item
+      \textbf{Welche Endianness hat der verwendete Rechner?
+      Begründen Sie Ihre Antwort.}
+
+      Wie in (a) begründet, ergibt sich die Ausgabe von
+      \lstinline[style=terminal]{1701278309} für das Jahr
+      aus dem Speicherformat Little-Endian.
+
+    \item
+      \textbf{Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?}
+
+      Wie in (a) begründet, ergäbe sich aus dem Speicherformat Big-Endian
+      die Ausgabe von \lstinline[style=terminal]{1701996389} für das Jahr.
+
+    \item
+      \textbf{Erklären Sie den Speicherzugriffsfehler.
+      (Es kann sein, daß sich der Fehler auf Ihrem Rechner nicht bemerkbar macht.
+      Er ist aber trotzdem vorhanden.)}
+
+      Die zwei in (a) mit "`?"' bezeichneten Speicherzellen
+      wurden ebenfalls überschrieben.
+      Dies ist in der Ausgabe zunächst nicht sichtbar,
+      bewirkt aber später den Speicherzugriffsfehler.
+
+      (Tatsächlich handelt es sich bei den überschriebenen Speicherzellen
+      um einen Teil der Rücksprungadresse, die \lstinline{main()} verwendet,
+      um mit \lstinline{return 0} an das Betriebssystem zurückzugeben.)
+
+  \end{enumerate}
+
+  \textbf{Hinweis 1:}
+  Um auf einen solchen Lösungsweg zu kommen, wird empfohlen,
+  "`geheimnisvolle"' Zahlen nach hexadezimal umzurechnen
+  und in Speicherzellen (Zweiergruppen von Hex-Ziffern) zu zerlegen.
+  Oft erkennt man dann direkt ASCII-Zeichen:
+  Großbuchstaben beginnen mit der Hex-Ziffer \lstinline{4} oder \lstinline{5},
+  Kleinbuchstaben mit \lstinline{6} oder \lstinline{7}.
+
+  \textbf{Hinweis 2:}
+  Um derartige Programmierfehler in der Praxis von vorneherein zu vermeiden,
+  wird empfohlen, anstelle von \lstinline{strcpy()}
+  grundsätzlich die Funktion \lstinline{strncpy()} zu verwenden.
+  Diese erwartet einen zusätzlichen Parameter,
+  der die maximal zulässige Länge des Strings enthält.
+  Ohne einen derartigen expliziten Parameter kann die Funktion nicht wissen,
+  wie lang die Variable ist, in der der String gespeichert werden soll.
+
+  \exercise{Objektorientierte Tier-Datenbank}
+
+  Das unten dargestellte Programm (Datei: \gitfile{hp}{2020ws/20210128}{aufgabe-3a.c})
+  soll Daten von Tieren verwalten.
+
+  Beim Compilieren erscheinen die folgende Fehlermeldungen:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2a.c -o aufgabe-2a¿
+    aufgabe-2a.c: In function 'main':
+    aufgabe-2a.c:31: error: 'animal' has no member named 'wings'
+    aufgabe-2a.c:37: error: 'animal' has no member named 'legs'
+  \end{lstlisting}
+
+  Der Programmierer nimmt die auf der nächsten Seite in Rot dargestellten Ersetzungen vor\\
+  (Datei: \gitfile{hp}{2020ws/20210128}{aufgabe-3b.c}).
+  Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2b.c -o aufgabe-2b¿
+    $ ¡./aufgabe-2b¿
+    A duck has 2 legs.
+    Error in animal: cow
+  \end{lstlisting}
+
+  \begin{itemize}
+    \item[(a)]
+      Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.
+      \points{2}
+    \item[(b)]
+      Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?
+      \points{3}
+    \item[(c)]
+      Erklären Sie die Ausgabe des Programms.
+      \points{5}
+    \item[(d)]
+      Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
+      das Programm so zu berichtigen, daß es die Eingabedaten
+      (``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.\\
+      \points{4}
+%    \item[(e)]
+%      Schreiben Sie das Programm so um,
+%      daß es keine expliziten Typumwandlungen mehr benötigt.\par
+%      Hinweis: Verwenden Sie \lstinline{union}.
+%      \points{4}
+%    \item[(f)]
+%      Schreiben Sie das Programm weiter um,
+%      so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
+%      dynamisch erzeugt.\par
+%      Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.
+%      \points{4}
+%    \item[(g)]
+%      Schreiben Sie das Programm weiter um,
+%      so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
+%      sondern stattdessen eine virtuelle Methode \lstinline{print()}
+%      aufgerufen wird.\par
+%      Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
+%      und initialisieren Sie diese in den Konstruktoren.
+%      \points{4}
+  \end{itemize}
+
+  \begin{minipage}[t]{0.34\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      #include <stdio.h>
+
+      #define ANIMAL     0
+      #define WITH_WINGS 1
+      #define WITH_LEGS  2
+
+      typedef struct animal
+      {
+        int type;
+        char *name;
+      } animal;
+
+      typedef struct with_wings
+      {
+        int wings;
+      } with_wings;
+
+      typedef struct with_legs
+      {
+        int legs;
+      } with_legs;
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.65\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      int main (void)
+      {
+        animal *a[2];
+
+        animal duck;
+        a[0] = &duck;
+        a[0]->type = WITH_WINGS;
+        a[0]->name = "duck";
+        a[0]->wings = 2;
+
+        animal cow;
+        a[1] = &cow;
+        a[1]->type = WITH_LEGS;
+        a[1]->name = "cow";
+        a[1]->legs = 4;
+
+        for (int i = 0; i < 2; i++)
+          if (a[i]->type == WITH_LEGS)
+            printf ("A %s has %d legs.\n", a[i]->name,
+                    ((with_legs *) a[i])-> legs);
+          else if (a[i]->type == WITH_WINGS)
+            printf ("A %s has %d wings.\n", a[i]->name,
+                    ((with_wings *) a[i])-> wings);
+          else
+            printf ("Error in animal: %s\n", a[i]->name);
+
+        return 0;
+      }
+    \end{lstlisting}
+    \begin{picture}(0,0)
+      \color{red}
+      \put(3.7,6.207){\vector(-1,0){0.7}}
+      \put(3.8,6.207){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_legs *) a[1])->legs = 4;}}}
+      \put(4.0,8.735){\vector(-1,0){0.7}}
+      \put(4.1,8.735){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_wings *) a[0])->wings = 2;}}}
+    \end{picture}
+  \end{minipage}
+
+  \solution
+
+  \begin{itemize}
+    \item[(a)]
+      \textbf{Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.}
+
+      \lstinline{a[0]} und \lstinline{a[1]}
+      sind gemäß der Deklaration \lstinline{animal *a[2]}
+      Zeiger auf Variablen vom Typ \lstinline{animal} (ein \lstinline{struct}).
+      Wenn man diesen Zeiger dereferenziert (\lstinline{->}),
+      erhält man eine \lstinline{animal}-Variable.
+      Diese enthält keine Datenfelder \lstinline{wings} bzw.\ \lstinline{legs}.
+
+    \item[(b)]
+      \textbf{Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?}
+
+      Durch die \emph{explizite Typumwandlung des Zeigers\/}
+      erhalten wir einen Zeiger auf eine \lstinline{with_wings}-
+      bzw.\ auf eine \lstinline{with_legs}-Variable.
+      Diese enthalten die Datenfelder \lstinline{wings} bzw.\ \lstinline{legs}.
+
+    \item[(c)]
+      \textbf{Erklären Sie die Ausgabe des Programms.}
+
+      Durch die explizite Typumwandlung des Zeigers
+      zeigt \lstinline{a[0]} auf eine \lstinline{with_wings}-Variable.
+      Diese enthält nur ein einziges Datenfeld \lstinline{wings},
+      das an genau derselben Stelle im Speicher liegt
+      wie \lstinline{a[0]->type}, also das Datenfeld \lstinline{type}
+      der \lstinline{animal}-Variable, auf die der Zeiger \lstinline{a[0]} zeigt.
+      Durch die Zuweisung der Zahl \lstinline{2}
+      an \lstinline{((with_wings *) a[0])->wings}
+      überschreiben wir also \lstinline{a[0]->type},
+      so daß das \lstinline{if} in der \lstinline{for}-Schleife
+      \lstinline{a[0]} als \lstinline{WITH_LEGS} erkennt.
+
+      Bei der Ausgabe \lstinline[style=terminal]{A duck has 2 legs.}
+      wird das Datenfeld \lstinline{((with_legs *)a[0])->legs} als Zahl ausgegeben.
+      Dieses Datenfeld befindet sich in denselben Speicherzellen wie
+      \lstinline{a[0]->type} und \lstinline{((with_wings *)} % :-(
+      \lstinline{a[0]->wings}
+      und hat daher ebenfalls den Wert 2.
+
+      Auf die gleiche Weise überschreiben wir durch die Zuweisung der Zahl 4
+      an \lstinline{((with_legs *) a[1])->legs}
+      das Datenfeld \lstinline{a[0]->type},
+      so daß das \lstinline{if} in der \lstinline{for}-Schleife
+      \lstinline{a[1]} als unbekanntes Tier (Nr.\ 4) erkennt und
+      \lstinline[style=terminal]{Error in animal: cow} ausgibt.
+
+    \item[(d)]
+      \textbf{Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
+      das Programm so zu berichtigen, daß es die Eingabedaten
+      (``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.}
+
+      Damit die \emph{Vererbung\/} zwischen den Objekten
+      \lstinline{animal}, \lstinline{with_wings} und \lstinline{with_legs}
+      funktioniert, müssen die abgeleiteten Klassen \lstinline{with_wings} und \lstinline{with_legs}
+      alle Datenfelder der Basisklasse \lstinline{animal} erben.
+      In C geschieht dies explizit; die Datenfelder müssen in den
+      abgeleiteten Klassen neu angegeben werden
+      (siehe \gitfile{hp}{2020ws/20210128}{loesung-3d-1.c}):
+
+      \begin{lstlisting}[gobble=8]
+        typedef struct animal
+        {
+          int type;
+          char *name;
+        } animal;
+
+        typedef struct with_wings
+        {
+          int type;
+          char *name;
+          int wings;
+        } with_wings;
+
+        typedef struct with_legs
+        {
+          int type;
+          char *name;
+          int legs;
+        } with_legs;
+      \end{lstlisting}
+
+      Zusätzlich ist es notwendig,
+      die Instanzen \lstinline{duck} und \lstinline{cow}
+      der abgeleiteten Klassen \lstinline{with_wings} und \lstinline{with_legs}
+      auch als solche zu deklarieren,
+      damit für sie genügend Speicher reserviert wird:
+
+      \begin{lstlisting}[gobble=8]
+        animal *a[2];
+
+        with_wings duck;
+        a[0] = (animal *) &duck;
+        a[0]->type = WITH_WINGS;
+        a[0]->name = "duck";
+        ((with_wings *) a[0])->wings = 2;
+
+        with_legs cow;
+        a[1] = (animal *) &cow;
+        a[1]->type = WITH_LEGS;
+        a[1]->name = "cow";
+        ((with_legs *) a[1])->legs = 4;
+      \end{lstlisting}
+
+      Wenn man dies vergißt und sie nur als \lstinline{animal} deklariert,
+      wird auch nur Speicherplatz für (kleinere)
+      \lstinline{animal}-Variable angelegt.
+      Dadurch kommt es zu Speicherzugriffen außerhalb der
+      deklarierten Variablen, was letztlich zu einem Absturz führt
+      (siehe \gitfile{hp}{2020ws/20210128}{loesung-3d-0f.c}).
+
+      Für die Zuweisung eines Zeigers auf \lstinline{duck}
+      an \lstinline{a[0]}, also an einen Zeiger auf \lstinline{animal}
+      wird eine weitere explizite Typumwandlung notwendig.
+      Entsprechendes gilt für die Zuweisung eines Zeigers auf \lstinline{cow}
+      an \lstinline{a[1]}.
+
+      Es ist sinnvoll, explizite Typumwandlungen so weit wie möglich zu vermeiden.
+      Es ist einfacher und gleichzeitig sicherer,
+      direkt in die Variablen \lstinline{duck} und \lstinline{cow}
+      zu schreiben, anstatt dies über die Zeiger \lstinline{a[0]}
+      und \lstinline{a[1]} zu tun
+      (siehe \gitfile{hp}{2020ws/20210128}{loesung-3d-2.c}):
+
+      \begin{lstlisting}[gobble=8]
+        animal *a[2];
+
+        with_wings duck;
+        a[0] = (animal *) &duck;
+        duck.type = WITH_WINGS;
+        duck.name = "duck";
+        duck.wings = 2;
+
+        with_legs cow;
+        a[1] = (animal *) &cow;
+        cow.type = WITH_LEGS;
+        cow.name = "cow";
+        cow.legs = 4;
+      \end{lstlisting}
+
+    \item[(e)]
+      \textbf{Schreiben Sie das Programm so um,
+      daß es keine expliziten Typumwandlungen mehr benötigt.}\par
+      \textbf{Hinweis: Verwenden Sie \lstinline{union}.}
+
+      Siehe \gitfile{hp}{2020ws/20210128}{loesung-3e.c}.
+      
+      Diese Lösung basiert auf \gitfile{hp}{2020ws/20210128}{loesung-3d-2.c},
+      da diese bereits weniger explizite Typumwandlungen enthält
+      als \gitfile{hp}{2020ws/20210128}{loesung-3d-1.c}.
+
+      Arbeitsschritte:
+      \begin{itemize}
+        \item
+          Umbenennen des Basistyps \lstinline{animal} in \lstinline{base},
+          damit wir den Bezeichner \lstinline{animal}
+          für die \lstinline{union} verwenden können
+        \item
+          Schreiben einer \lstinline{union animal},
+          die die drei Klassen \lstinline{base},
+          \lstinline{with_wings} und \lstinline{with_legs}
+          als Datenfelder enthält
+        \item
+          Umschreiben der Initialisierungen:
+          Zugriff auf Datenfelder erfolgt nun durch
+          z.\,B.\ \lstinline{a[0]->b.name}.
+          Hierbei ist \lstinline{b} der Name des \lstinline{base}-Datenfelds
+          innerhalb der \lstinline{union animal}.
+        \item
+          Auf gleiche Weise schreiben wir die \lstinline{if}-Bedingungen
+          innerhalb der \lstinline{for}-Schleife
+          sowie die Parameter der \lstinline{printf()}-Aufrufe um.
+      \end{itemize}
+      Explizite Typumwandlungen sind nun nicht mehr nötig.
+
+      Nachteil dieser Lösung:
+      Jede Objekt-Variable belegt nun Speicherplatz
+      für die gesamte \lstinline{union animal},
+      anstatt nur für die benötigte Variable vom Typ
+      \lstinline{with_wings} oder \lstinline{with_legs}.
+      Dies kann zu einer Verschwendung von Speicherplatz führen,
+      auch wenn dies in diesem Beispielprogramm tatsächlich nicht der Fall ist.
+
+    \item[(f)]
+      \textbf{Schreiben Sie das Programm weiter um,
+      so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
+      dynamisch erzeugt.}\par
+      \textbf{Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.}
+
+      Siehe \gitfile{hp}{2020ws/20210128}{loesung-3f.c}.
+
+    \item[(g)]
+      \textbf{Schreiben Sie das Programm weiter um,
+      so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
+      sondern stattdessen eine virtuelle Methode \lstinline{print()}
+      aufgerufen wird.}\par
+      \textbf{Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
+      und initialisieren Sie diese in den Konstruktoren.}
+
+      Siehe \gitfile{hp}{2020ws/20210128}{loesung-3g.c}.
+
+  \end{itemize}
+
+\end{document}
diff --git a/20210128/hp-uebung-20210128.pdf b/20210128/hp-uebung-20210128.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..350451858390509e6e1c0b4e13eee0ebf42d2f8f
Binary files /dev/null and b/20210128/hp-uebung-20210128.pdf differ
diff --git a/20210128/hp-uebung-20210128.tex b/20210128/hp-uebung-20210128.tex
new file mode 100644
index 0000000000000000000000000000000000000000..49b831bc5b00720a0e3ff714da0aff587878253b
--- /dev/null
+++ b/20210128/hp-uebung-20210128.tex
@@ -0,0 +1,305 @@
+% hp-uebung-20210128.pdf - Exercises on Low-Level Programming
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Speicherformate von Zahlen, Personen-Datenbank, objektorientierte Tier-Datenbank
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+
+\begin{document}
+
+%  \thispagestyle{empty}
+
+  \section*{Hardwarenahe Programmierung\\
+            Übungsaufgaben -- 28.\ Januar 2021}
+
+  Diese Übung enthält Punkteangaben wie in einer Klausur.
+  Um zu "`bestehen"', müssen Sie innerhalb von 100 Minuten
+  unter Verwendung ausschließlich zugelassener Hilfsmittel
+  17 Punkte (von insgesamt \totalpoints) erreichen.
+
+  \exercise{Speicherformate von Zahlen}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210128}{aufgabe-1.c}):
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <stdint.h>
+
+    typedef struct
+    {
+      uint32_t a;
+      uint64_t b;
+      uint8_t c;
+    } three_numbers;
+
+    int main (void)
+    {
+      three_numbers xyz = { 1819042120, 2410670883059281007, 0 };
+      printf ("%s\n", &xyz);
+      return 0;
+    }
+  \end{lstlisting}
+
+  Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\
+  (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür,
+  daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.)
+
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -Wall -m32 aufgabe-2.c -o aufgabe-2¿
+    aufgabe-2.c: In function "main":
+    aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", but
+    argument 2 has type "three_numbers * {aka struct <anonymous> *}" [-Wformat=]
+       printf ("%s\n", &xyz);
+                 ^
+    $ ¡./aufgabe-2¿
+    Hallo, Welt!
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie die beim Compilieren auftretende Warnung.
+      \points{2}
+    \item
+      Erklären Sie die Ausgabe des Programms.
+      \points{4}
+    \item
+      Welche Endianness hat der verwendete Rechner?
+      Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?
+      \points{2}
+    \item
+      Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\
+      (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür,
+      daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.)
+      \begin{lstlisting}[style=terminal,gobble=8]
+        $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿
+        aufgabe-2.c: In function "main":
+        aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *",
+        but argument 2 has type "three_numbers * {aka struct <anonymous> *}"
+        [-Wformat=]
+           printf ("%s\n", &xyz);
+                     ^
+        $ ¡./aufgabe-2¿
+        Hall5V
+      \end{lstlisting}
+      (Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)\par
+      Erklären Sie die geänderte Ausgabe des Programms.
+      \points{3}
+  \end{enumerate}
+
+  \clearpage
+  \exercise{Personen-Datenbank}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2020ws/20210128}{aufgabe-2.c}):
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    typedef struct
+    {
+      char first_name[10];
+      char family_name[20];
+      char day, month;
+      int year;
+    } person;
+
+    int main (void)
+    {
+      person sls;
+      sls.day = 26;
+      sls.month = 7;
+      sls.year = 1951;
+      strcpy (sls.first_name, "Sabine");
+      strcpy (sls.family_name, "Leutheusser-Schnarrenberger");
+      printf ("%s %s wurde am %d.%d.%d geboren.\n",
+              sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+      return 0;
+    }
+  \end{lstlisting}
+
+  Die Standard-Funktion \lstinline{strcpy()} bewirkt ein Kopieren eines Strings
+  von rechts nach links, hier also z.\,B.\ die Zuweisung der String-Konstanten
+  \lstinline{"Sabine"} an die String-Variable \lstinline{sls.first_name[]}.
+
+  Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\
+  (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür,
+  daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.)
+
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -Wall -O -m32 aufgabe-2.c -o aufgabe-2¿
+    $ ¡./aufgabe-2¿
+    Sabine Leutheusser-Schnarrenberger wurde am 110.98.1701278309 geboren.
+    Speicherzugriffsfehler
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie die Ausgabe des Programms einschließlich der Zahlenwerte.
+      \points{4}
+    \item
+      Welche Endianness hat der verwendete Rechner?
+      Begründen Sie Ihre Antwort.
+      \points{1}
+    \item
+      Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?
+      \points{2}
+    \item
+      Erklären Sie den Speicherzugriffsfehler.
+      (Es kann sein, daß sich der Fehler auf Ihrem Rechner nicht bemerkbar macht.
+      Er ist aber trotzdem vorhanden.)
+      \points{2}
+  \end{enumerate}
+
+  \clearpage
+  \exercise{Objektorientierte Tier-Datenbank}
+
+  Das unten dargestellte Programm (Datei: \gitfile{hp}{2020ws/20210128}{aufgabe-3a.c})
+  soll Daten von Tieren verwalten.
+
+  Beim Compilieren erscheinen die folgende Fehlermeldungen:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2a.c -o aufgabe-2a¿
+    aufgabe-2a.c: In function 'main':
+    aufgabe-2a.c:31: error: 'animal' has no member named 'wings'
+    aufgabe-2a.c:37: error: 'animal' has no member named 'legs'
+  \end{lstlisting}
+
+  Der Programmierer nimmt die auf der nächsten Seite in Rot dargestellten Ersetzungen vor\\
+  (Datei: \gitfile{hp}{2020ws/20210128}{aufgabe-3b.c}).
+  Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet:
+  \begin{lstlisting}[style=terminal]
+    $ ¡gcc -std=c99 -Wall -O aufgabe-2b.c -o aufgabe-2b¿
+    $ ¡./aufgabe-2b¿
+    A duck has 2 legs.
+    Error in animal: cow
+  \end{lstlisting}
+
+  \begin{itemize}
+    \item[(a)]
+      Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.
+      \points{2}
+    \item[(b)]
+      Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?
+      \points{3}
+    \item[(c)]
+      Erklären Sie die Ausgabe des Programms.
+      \points{5}
+    \item[(d)]
+      Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
+      das Programm so zu berichtigen, daß es die Eingabedaten
+      (``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.\\
+      \points{4}
+%    \item[(e)]
+%      Schreiben Sie das Programm so um,
+%      daß es keine expliziten Typumwandlungen mehr benötigt.\par
+%      Hinweis: Verwenden Sie \lstinline{union}.
+%      \points{4}
+%    \item[(f)]
+%      Schreiben Sie das Programm weiter um,
+%      so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
+%      dynamisch erzeugt.\par
+%      Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.
+%      \points{4}
+%    \item[(g)]
+%      Schreiben Sie das Programm weiter um,
+%      so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
+%      sondern stattdessen eine virtuelle Methode \lstinline{print()}
+%      aufgerufen wird.\par
+%      Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
+%      und initialisieren Sie diese in den Konstruktoren.
+%      \points{4}
+  \end{itemize}
+
+  \begin{minipage}[t]{0.34\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      #include <stdio.h>
+
+      #define ANIMAL     0
+      #define WITH_WINGS 1
+      #define WITH_LEGS  2
+
+      typedef struct animal
+      {
+        int type;
+        char *name;
+      } animal;
+
+      typedef struct with_wings
+      {
+        int wings;
+      } with_wings;
+
+      typedef struct with_legs
+      {
+        int legs;
+      } with_legs;
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.65\textwidth}
+    \begin{lstlisting}[gobble=6,xleftmargin=0pt]
+      int main (void)
+      {
+        animal *a[2];
+
+        animal duck;
+        a[0] = &duck;
+        a[0]->type = WITH_WINGS;
+        a[0]->name = "duck";
+        a[0]->wings = 2;
+
+        animal cow;
+        a[1] = &cow;
+        a[1]->type = WITH_LEGS;
+        a[1]->name = "cow";
+        a[1]->legs = 4;
+
+        for (int i = 0; i < 2; i++)
+          if (a[i]->type == WITH_LEGS)
+            printf ("A %s has %d legs.\n", a[i]->name,
+                    ((with_legs *) a[i])-> legs);
+          else if (a[i]->type == WITH_WINGS)
+            printf ("A %s has %d wings.\n", a[i]->name,
+                    ((with_wings *) a[i])-> wings);
+          else
+            printf ("Error in animal: %s\n", a[i]->name);
+
+        return 0;
+      }
+    \end{lstlisting}
+    \begin{picture}(0,0)
+      \color{red}
+      \put(3.7,6.207){\vector(-1,0){0.7}}
+      \put(3.8,6.207){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_legs *) a[1])->legs = 4;}}}
+      \put(4.0,8.735){\vector(-1,0){0.7}}
+      \put(4.1,8.735){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_wings *) a[0])->wings = 2;}}}
+    \end{picture}
+  \end{minipage}
+
+  \begin{flushright}
+    \textit{Viel Erfolg!}
+  \end{flushright}
+
+  \makeatletter
+    \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
+  \makeatother
+
+\end{document}
diff --git a/20210128/loesung-1-1.c b/20210128/loesung-1-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..175923f7250d0747a21df5f33f8a3761393d1d7f
--- /dev/null
+++ b/20210128/loesung-1-1.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdint.h>
+
+typedef struct
+{
+  uint32_t a;
+  uint64_t b;
+  uint8_t c;
+} three_numbers;
+
+int main (void)
+{
+  three_numbers xyz = { 1819042120, 2410670883059281007, 0 };
+  printf ("%x %x %x\n", xyz.a, xyz.b, xyz.c);
+  printf ("%08x %016x %02x\n", xyz.a, xyz.b, xyz.c);
+  printf ("%s\n", &xyz);
+  return 0;
+}
diff --git a/20210128/loesung-1-2.c b/20210128/loesung-1-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..07ca06832cc58c1b8243f9afd05aec57bb12b1c4
--- /dev/null
+++ b/20210128/loesung-1-2.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdint.h>
+
+typedef struct
+{
+  uint32_t a;
+  uint64_t b;
+  uint8_t c;
+} three_numbers;
+
+int main (void)
+{
+  three_numbers xyz = { 1819042120, 2410670883059281007, 0 };
+  printf ("%x %lx %x\n", xyz.a, xyz.b, xyz.c);
+  printf ("%08x %016lx %02x\n", xyz.a, xyz.b, xyz.c);
+  printf ("%s\n", &xyz);
+  return 0;
+}
diff --git a/20210128/loesung-2-1.c b/20210128/loesung-2-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..416c5dfa2cba2f7dc68b72551ec6a5c8ce8bab79
--- /dev/null
+++ b/20210128/loesung-2-1.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <string.h>
+
+typedef struct
+{
+  char first_name[10];
+  char family_name[20];
+  char day, month;
+  int year;
+} person;
+
+int main (void)
+{
+  person sls;
+  strcpy (sls.first_name, "Sabine");
+  strcpy (sls.family_name, "Leutheusser-Schnarrenberger");
+  sls.day = 26;
+  sls.month = 7;
+  sls.year = 1951;
+  printf ("%s %s wurde am %d.%d.%d geboren.\n",
+          sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+  return 0;
+}
diff --git a/20210128/loesung-2-2.c b/20210128/loesung-2-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..825373e61475ebc67e9cac6929b6e004715a7cad
--- /dev/null
+++ b/20210128/loesung-2-2.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <string.h>
+
+typedef struct
+{
+  char first_name[10];
+  char family_name[20];
+  char day, month;
+  int year;
+} person;
+
+int main (void)
+{
+  person sls;
+  sls.day = 26;
+  sls.month = 7;
+  sls.year = 1951;
+  strncpy (sls.first_name, "Sabine", 10);
+  strncpy (sls.family_name, "Leutheusser-Schnarrenberger", 20);
+  printf ("%s %s wurde am %d.%d.%d geboren.\n",
+          sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+  return 0;
+}
diff --git a/20210128/loesung-2-3.c b/20210128/loesung-2-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a4b1bfaf9e67a164ee865a0ae4ef69606255de0
--- /dev/null
+++ b/20210128/loesung-2-3.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <string.h>
+
+typedef struct
+{
+  char first_name[10];
+  char family_name[20];
+  char day, month;
+  int year;
+} person;
+
+int main (void)
+{
+  person sls;
+  sls.day = 26;
+  sls.month = 7;
+  sls.year = 1951;
+  strncpy (sls.first_name, "Sabine", 9);
+  strncpy (sls.family_name, "Leutheusser-Schnarrenberger", 19);
+  printf ("%s %s wurde am %d.%d.%d geboren.\n",
+          sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+  return 0;
+}
diff --git a/20210128/loesung-2-4.c b/20210128/loesung-2-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..3c635dfa7e3923eb678469166bf218e1640927a2
--- /dev/null
+++ b/20210128/loesung-2-4.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <string.h>
+
+typedef struct
+{
+  char first_name[10];
+  char family_name[20];
+  char day, month;
+  int year;
+} person;
+
+int main (void)
+{
+  person sls;
+  sls.day = 26;
+  sls.month = 7;
+  sls.year = 1951;
+  strncpy (sls.first_name, "Sabine", 9);
+  sls.first_name[9] = 0;
+  strncpy (sls.family_name, "Leutheusser-Schnarrenberger", 19);
+  sls.family_name[19] = 0;
+  printf ("%s %s wurde am %d.%d.%d geboren.\n",
+          sls.first_name, sls.family_name, sls.day, sls.month, sls.year);
+  return 0;
+}
diff --git a/20210128/loesung-3d-0f.c b/20210128/loesung-3d-0f.c
new file mode 100644
index 0000000000000000000000000000000000000000..04b2d3e8956f4790b3f2ffdf3a314994c640513e
--- /dev/null
+++ b/20210128/loesung-3d-0f.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  ((with_wings *) a[0])->wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  ((with_legs *) a[1])->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20210128/loesung-3d-1.c b/20210128/loesung-3d-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..349523a7d99e33ba81094ffbc8907773b5a3a251
--- /dev/null
+++ b/20210128/loesung-3d-1.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  with_wings duck;
+  a[0] = (animal *) &duck;
+  a[0]->type = WITH_WINGS;
+  a[0]->name = "duck";
+  ((with_wings *) a[0])->wings = 2;
+
+  with_legs cow;
+  a[1] = (animal *) &cow;
+  a[1]->type = WITH_LEGS;
+  a[1]->name = "cow";
+  ((with_legs *) a[1])->legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20210128/loesung-3d-2.c b/20210128/loesung-3d-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f831a75eda1f3e784c8e6c1f24a83d9d6b55ee6c
--- /dev/null
+++ b/20210128/loesung-3d-2.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct animal
+{
+  int type;
+  char *name;
+} animal;
+
+typedef struct with_wings
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct with_legs
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+int main (void)
+{
+  animal *a[2];
+
+  with_wings duck;
+  a[0] = (animal *) &duck;
+  duck.type = WITH_WINGS;
+  duck.name = "duck";
+  duck.wings = 2;
+
+  with_legs cow;
+  a[1] = (animal *) &cow;
+  cow.type = WITH_LEGS;
+  cow.name = "cow";
+  cow.legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->name,
+              ((with_legs *) a[i])-> legs);
+    else if (a[i]->type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->name,
+              ((with_wings *) a[i])-> wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->name);
+
+  return 0;
+}
diff --git a/20210128/loesung-3e.c b/20210128/loesung-3e.c
new file mode 100644
index 0000000000000000000000000000000000000000..b984d9253b9c379a88f0fc0ca130c88c3103f8f3
--- /dev/null
+++ b/20210128/loesung-3e.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct
+{
+  int type;
+  char *name;
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+typedef union
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+int main (void)
+{
+  animal *a[2];
+
+  animal duck;
+  a[0] = &duck;
+  duck.b.type = WITH_WINGS;
+  duck.b.name = "duck";
+  duck.w.wings = 2;
+
+  animal cow;
+  a[1] = &cow;
+  cow.b.type = WITH_LEGS;
+  cow.b.name = "cow";
+  cow.l.legs = 4;
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->b.type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->b.name,
+              a[i]->l.legs);
+    else if (a[i]->b.type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->b.name,
+              a[i]->w.wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->b.name);
+
+  return 0;
+}
diff --git a/20210128/loesung-3f.c b/20210128/loesung-3f.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b949e6365fc3839e6adc7661e0f8b4dd0c059df
--- /dev/null
+++ b/20210128/loesung-3f.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+typedef struct
+{
+  int type;
+  char *name;
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  int legs;
+} with_legs;
+
+typedef union
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+animal *new_with_wings (char *name, int wings)
+{
+  animal *a = malloc (sizeof (with_wings));
+  a->b.type = WITH_WINGS;
+  a->b.name = name;
+  a->w.wings = wings;
+  return a;
+}
+
+animal *new_with_legs (char *name, int legs)
+{
+  animal *a = malloc (sizeof (with_legs));
+  a->b.type = WITH_LEGS;
+  a->b.name = name;
+  a->l.legs = legs;
+  return a;
+}
+
+int main (void)
+{
+  animal *a[2] = { new_with_wings ("duck", 2),
+                   new_with_legs ("cow", 4) };
+
+  for (int i = 0; i < 2; i++)
+    if (a[i]->b.type == WITH_LEGS)
+      printf ("A %s has %d legs.\n", a[i]->b.name,
+              a[i]->l.legs);
+    else if (a[i]->b.type == WITH_WINGS)
+      printf ("A %s has %d wings.\n", a[i]->b.name,
+              a[i]->w.wings);
+    else
+      printf ("Error in animal: %s\n", a[i]->b.name);
+
+  return 0;
+}
diff --git a/20210128/loesung-3g.c b/20210128/loesung-3g.c
new file mode 100644
index 0000000000000000000000000000000000000000..b453a52dbe0ef27399255819808b3f6e562ba3ef
--- /dev/null
+++ b/20210128/loesung-3g.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ANIMAL     0
+#define WITH_WINGS 1
+#define WITH_LEGS  2
+
+union animal;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+} base;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+  int wings;
+} with_wings;
+
+typedef struct
+{
+  int type;
+  char *name;
+  void (*print) (union animal *this);
+  int legs;
+} with_legs;
+
+typedef union animal
+{
+  base b;
+  with_wings w;
+  with_legs l;
+} animal;
+
+void print_with_wings (animal *this)
+{
+  printf ("A %s has %d wings.\n", this->b.name, this->w.wings);
+}
+
+void print_with_legs (animal *this)
+{
+  printf ("A %s has %d legs.\n", this->b.name, this->l.legs);
+}
+
+animal *new_with_wings (char *name, int wings)
+{
+  animal *a = malloc (sizeof (with_wings));
+  a->b.type = WITH_WINGS;
+  a->b.name = name;
+  a->b.print = print_with_wings;
+  a->w.wings = wings;
+  return a;
+}
+
+animal *new_with_legs (char *name, int legs)
+{
+  animal *a = malloc (sizeof (with_legs));
+  a->b.type = WITH_LEGS;
+  a->b.name = name;
+  a->b.print = print_with_legs;
+  a->l.legs = legs;
+  return a;
+}
+
+int main (void)
+{
+  animal *a[2] = { new_with_wings ("duck", 2),
+                   new_with_legs ("cow", 4) };
+  for (int i = 0; i < 2; i++)
+    a[i]->b.print (a[i]);
+  return 0;
+}
diff --git a/20210128/logo-hochschule-bochum-cvh-text-v2.pdf b/20210128/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20210128/logo-hochschule-bochum-cvh-text-v2.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum-cvh-text-v2.pdf
\ No newline at end of file
diff --git a/20210128/logo-hochschule-bochum.pdf b/20210128/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20210128/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20210128/pgscript.sty b/20210128/pgscript.sty
new file mode 120000
index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b
--- /dev/null
+++ b/20210128/pgscript.sty
@@ -0,0 +1 @@
+../common/pgscript.sty
\ No newline at end of file
diff --git a/20210128/pgslides.sty b/20210128/pgslides.sty
new file mode 120000
index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64
--- /dev/null
+++ b/20210128/pgslides.sty
@@ -0,0 +1 @@
+../common/pgslides.sty
\ No newline at end of file