diff --git a/20231214/aufgabe-2a.c b/20231214/aufgabe-2a.c
new file mode 100644
index 0000000000000000000000000000000000000000..61b6e79400afbb8ac0609eb1b72c04b83a0fce41
--- /dev/null
+++ b/20231214/aufgabe-2a.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/20231214/aufgabe-2b.c b/20231214/aufgabe-2b.c
new file mode 100644
index 0000000000000000000000000000000000000000..2cf3b56f4540f399d3761b0de929d80a1f1de611
--- /dev/null
+++ b/20231214/aufgabe-2b.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/20231214/hp-20231214.pdf b/20231214/hp-20231214.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..b6d6d49611933ec9543ecdfcadb6cb4c8c625d41
Binary files /dev/null and b/20231214/hp-20231214.pdf differ
diff --git a/20231214/hp-20231214.tex b/20231214/hp-20231214.tex
new file mode 100644
index 0000000000000000000000000000000000000000..ea69ab90e96f387b0cc8f85ba59cd7a037a3cbf0
--- /dev/null
+++ b/20231214/hp-20231214.tex
@@ -0,0 +1,835 @@
+% hp-20231214.pdf - Lecture Slides on Low-Level Programming
+% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  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: Einführung
+
+\documentclass[10pt,t]{beamer}
+
+\usepackage{pgslides}
+\usepackage{tikz}
+\usepackage{rotating}
+
+\newcommand{\redurl}[1]{\href{#1}{\color{red}\nolinkurl{#1}}}
+
+\title{Hardwarenahe Programmierung}
+\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
+\date{14.\ Dezember 2023}
+
+\begin{document}
+
+\maketitleframe
+
+\title{Hardwarenahe Programmierung}
+
+\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{Hardwarenahe Programmierung}
+    \item[\textbf{5}] \textbf{Algorithmen}
+      \begin{itemize}
+        \item[5.1] Differentialgleichungen
+        \item[5.2] Rekursion
+        \color{medgreen}
+        \item[5.3] Aufwandsabschätzungen
+      \end{itemize}
+    \item[\textbf{6}] \textbf{Objektorientierte Programmierung}
+      \begin{itemize}
+        \color{red}
+        \item[6.0] Dynamische Speicherverwaltung
+        \item[6.1] Konzepte und Ziele
+        \item[6.2] Beispiel: Zahlen und Buchstaben
+        \color{black}
+        \item[6.3] Unions
+        \item[6.4] Virtuelle Methoden
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+      \end{itemize}
+    \item[\textbf{7}] \textbf{Datenstrukturen}
+  \end{itemize}
+
+\end{frame}
+
+\setcounter{section}{4}
+\section{Algorithmen}
+\setcounter{subsection}{2}
+\subsection{Aufwandsabschätzungen \protect\color{gray}-- Komplexitätsanalyse}
+
+\begin{frame}[fragile]
+
+%  \newcommand{\w}{\hspace*{0.75pt}}
+
+  \showsubsection
+
+  \begin{picture}(0,0)
+    \put(7.6,-0.5){%
+      \begin{minipage}[t]{5.3cm}
+%        \vspace*{-1.0cm}\includegraphics{landau-symbols.pdf}
+        \vspace*{-1.0cm}\alt<16->{\includegraphics{landau-symbols-3.pdf}}%
+                       {\alt<15->{\includegraphics{landau-symbols-2.pdf}}%
+                                 {\includegraphics{landau-symbols.pdf}}}
+        \small
+        \begin{description}\itemsep0pt\leftskip-0.5cm
+          \item[$n$:] Eingabedaten
+          \item[$g(n)$:] Rechenzeit
+        \end{description}
+      \end{minipage}}
+  \end{picture}
+
+  \vspace*{-\bigskipamount}
+
+  Wann ist ein Programm "`schnell"'?
+
+  \medskip
+
+  \begin{onlyenv}<1-2>
+      Türme von Hanoi: $\mathcal{O}(2^n)$
+      \par\medskip
+      Für jede zusätzliche Scheibe\\verdoppelt sich die Rechenzeit!
+      \begin{itemize}
+        \arrowitem
+          $\frac{30,672\,\text{s}\,\cdot\,2^{32}}{3600\,\cdot\,24\,\cdot\,365,25} \approx 4174$
+          Jahre\\[\smallskipamount]
+          für 64 Scheiben
+      \end{itemize}
+
+      \bigskip
+  \end{onlyenv}
+
+  \begin{onlyenv}<2->
+    Faustregel:\\Schachtelung der Schleifen zählen\\
+    $k$ Schleifen ineinander \textarrow\ $\mathcal{O}(n^k)$
+
+    \bigskip
+  \end{onlyenv}
+
+  \begin{onlyenv}<3-13>
+    \textbf{Beispiel: Sortieralgorithmen}
+
+    \smallskip
+
+    Anzahl der Vergleiche bei $n$ Strings
+    \begin{itemize}
+      \item
+        Maximum suchen \pause[4]mit Schummeln\pause: $\mathcal{O}(1)$
+      \pause
+      \item
+        Maximum suchen\pause: $\mathcal{O}(n)$
+      \pause
+      \item
+        Selection-Sort\pause: $\mathcal{O}(n^2)$
+      \pause
+      \item
+        Bubble-Sort\pause: $\mathcal{O}(n)$ bis $\mathcal{O}(n^2)$
+      \pause
+      \item
+        Quicksort\pause: $\mathcal{O}(n\log n)$ bis $\mathcal{O}(n^2)$
+    \end{itemize}
+
+  \end{onlyenv}
+
+  \begin{onlyenv}<14>
+    \textbf{Wie schnell ist RSA-Verschlüsselung?}
+
+    \smallskip
+
+    \begin{math}
+      c = m^e\,\%\,N
+    \end{math}
+    \quad
+    ("`$\%$"' = "`modulo"')
+
+    \medskip
+
+    \begin{lstlisting}[gobble=6,xleftmargin=2em]
+      int c = 1;
+      for (int i = 0; i < e; i++)
+        c = (c * m) % N;
+    \end{lstlisting}
+
+    \smallskip
+
+    \begin{itemize}
+      \item
+        $\mathcal{O}(e)$ Iterationen
+%      \item
+%        wenn $n$ die Anzahl der Binärziffern (Bits) von $e$ ist:
+%        $\mathcal{O}(2^n)$ Iterationen
+      \item
+        mit Trick:
+        $\mathcal{O}(\log e)$ Iterationen ($\log e$ = Anzahl der Ziffern von $e$)
+    \end{itemize}
+
+    \smallskip
+
+    Jede Iteration enthält eine Multiplikation und eine Division.\\
+    Aufwand dafür: $\mathcal{O}(\log e)$\\
+    \textarrow\ Gesamtaufwand: $\mathcal{O}\bigl((\log e)^2\bigr)$
+
+  \end{onlyenv}
+
+  \begin{onlyenv}<15->
+
+    \textbf{Wie schnell ist RSA?}\\
+
+    \smallskip
+
+    ($n$ = typische beteiligte Zahl, z.\,B. $e,p,q$)
+
+    \begin{itemize}
+      \item
+        Ver- und Entschlüsselung (Exponentiation):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}}
+      \item
+        Schlüsselerzeugung (Berechnung von $d$):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}}
+      \item
+        Verschlüsselung brechen (Primfaktorzerlegung):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\bigl(2^{\sqrt{\log n\,\cdot\,\log\log n}}\bigr)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}\bigl(2^{\sqrt{n\log n}}\bigr)$}}
+    \end{itemize}
+
+    \vspace{0cm plus 1filll}
+
+    \textbf{Die Sicherheit von RSA beruht darauf,
+    daß das Brechen der Verschlüsselung aufwendiger ist als
+    \boldmath$\mathcal{O}\bigl((\log n)^k\bigr)$ (für beliebiges $k$).}
+
+    \vspace*{0.65cm}
+
+  \end{onlyenv}
+
+\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{Klassenhierarchie} 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}
+
+\iffalse
+
+\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}
+
+\fi
+
+\end{document}
diff --git a/20231214/hp-musterloesung-20231214.pdf b/20231214/hp-musterloesung-20231214.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..300f360709ed082ffd0fb1709acbaf32ed04237b
Binary files /dev/null and b/20231214/hp-musterloesung-20231214.pdf differ
diff --git a/20231214/hp-musterloesung-20231214.tex b/20231214/hp-musterloesung-20231214.tex
new file mode 100644
index 0000000000000000000000000000000000000000..c704b037e61cc21aefc8a4f22bd81f4d36ce7d16
--- /dev/null
+++ b/20231214/hp-musterloesung-20231214.tex
@@ -0,0 +1,538 @@
+% hp-musterloesung-20231214.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  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: Länge von Strings, Einfügen in Strings (Ergänzung)
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{gnuplot-lua-tikz}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- 14.\ Dezember 2023}
+
+  \exercise{Dynamisches Bit-Array}
+
+  Schreiben Sie die folgenden Funktionen zur Verwaltung eines dynamischen Bit-Arrays:
+  \begin{itemize}
+    \item
+      \lstinline{void bit_array_init (int n)}\\
+      Das Array initialisieren, so daß man \lstinline{n} Bits darin speichern kann.\\
+      Die Array-Größe \lstinline{n} ist keine Konstante, sondern erst im laufenden Programm bekannt.\\
+      Die Bits sollen auf den Anfangswert 0 initialisiert werden.
+    \item
+      \lstinline{void bit_array_set (int i, int value)}\\
+      Das Bit mit dem Index \lstinline{i} auf den Wert \lstinline{value} setzen.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen;
+      der Wert \lstinline{value} darf 1 oder 0 sein.
+    \item
+      \lstinline{void bit_array_flip (int i)}\\
+      Das Bit mit dem Index \lstinline{i} auf den entgegengesetzten Wert setzen,\\
+      also auf 1, wenn er vorher 0 ist, bzw.\ auf 0, wenn er vorher 1 ist.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
+    \item
+      \lstinline{int bit_array_get (int i)}\\
+      Den Wert des Bit mit dem Index \lstinline{i} zurückliefern.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
+    \item
+      \lstinline{void bit_array_resize (int new_n)}\\
+      Die Größe des Arrays auf \lstinline{new_n} Bits ändern.\\
+      Dabei soll der Inhalt des Arrays, soweit er in die neue Größe paßt, erhalten bleiben.\\
+      Neu hinzukommende Bits sollen auf 0 initialisiert werden.
+    \item
+      \lstinline{void bit_array_done (void)}\\
+      Den vom Array belegten Speicherplatz wieder freigeben.
+  \end{itemize}
+  Bei Bedarf dürfen Sie den Funktionen zusätzliche Parameter mitgeben,
+  beispielsweise um mehrere Arrays parallel verwalten zu können.
+  (In der objektorientierten Programmierung wäre dies der implizite Parameter \lstinline{this},
+  der auf die Objekt-Struktur zeigt.)
+
+  Die Bits sollen möglichst effizient gespeichert werden,
+  z.\,B.\ jeweils 8 Bits in einer \lstinline{uint8_t}-Variablen.
+
+  Die Funktionen sollen möglichst robust sein,
+  d.\,h.\ das Programm darf auch bei unsinnigen Parameterwerten nicht abstürzen,
+  sondern soll eine Fehlermeldung ausgeben.
+
+  \medskip
+
+  Die folgenden \textbf{Hinweise} beschreiben
+  einen möglichen Weg, die Aufgabe zu lösen.
+  Es seht Ihnen frei, die Aufgabe auch auf andere Weise zu lösen.
+  \begin{itemize}
+    \item
+      Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat,
+      und schreiben Sie zunächst nur die Funktionen
+      \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und
+      \lstinline{bit_array_get()}.
+    \item
+      Verallgemeinern Sie nun auf eine konstante Länge,
+      bei der es sich um ein Vielfaches von 8 handelt.
+    \item
+      Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte.
+      Damit können Sie sich gleichzeitig von der Bedingung lösen,
+      daß die Länge des Arrays ein Vielfaches von 8 sein muß.
+    \item
+      Gehen Sie nun von einem statischen zu einem dynamischen Array über,
+      und implementieren sie die Funktionen \lstinline{bit_array_init()},
+      \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}.
+  \end{itemize}
+
+%  \points{14}
+%
+%  \medskip
+%
+%  (Hinweis für die Klausur:
+%  Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.)
+
+  \clearpage
+
+  \solution
+
+  Die hier vorgestellte Lösung folgt den Hinweisen.
+  \begin{itemize}
+    \item
+      \textbf{Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat,
+      und schreiben Sie zunächst nur die Funktionen
+      \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und
+      \lstinline{bit_array_get()}.}
+
+      Siehe: \gitfile{hp}{2023ws/20231214}{loesung-1-1.c}
+
+      Wir speichern in jedem der acht Bit einer \lstinline{uint8_t}-Variablen
+      jeweils eine Zahl, die 0 oder 1 sein kann.
+      Dies geschieht durch Setzen bzw.\ Löschen bzw.\ Umklappen einzelner Bits
+      in der Variablen.
+
+      Das Programm enthält zusätzlich eine Funktion \lstinline{output()},
+      mit der man sich den Inhalt des Arrays anzeigen lassen kann,
+      sowie ein Hauptprogramm \lstinline{main()}, um die Funktionen zu testen.
+
+    \item
+      \textbf{Verallgemeinern Sie nun auf eine konstante Länge,
+      bei der es sich um ein Vielfaches von 8 handelt.}
+
+      Siehe: \gitfile{hp}{2023ws/20231214}{loesung-1-2.c}
+
+      In diesem Programm setzen wir die Länge auf konstant \lstinline{LENGTH} Bits,
+      wobei es sich um eine Präprozessor-Konstante mit dem Wert 32 handelt.
+
+      Um \lstinline{LENGTH} Bits zu speichern, benötigen wir ein Array
+      der Länge \lstinline{LENGTH / 8} Bytes.
+
+      Um auf ein einzelnes Bit zuzugreifen, müssen wir zunächst ermitteln,
+      in welchem der Bytes sich befindet. Außerdem interessieren wir uns
+      für die Nummer des Bits innerhalb des Bytes.
+      Den Array-Index des Bytes erhalten wir, indem wir den Index des Bits
+      durch 8 dividieren. Der bei dieser Division verbleibende Rest ist die
+      Nummer des Bits innerhalb des Bytes.
+
+      Diese Rechnungen führen wir in den drei Funktionen
+      \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und
+      \lstinline{bit_array_get()} durch.
+      (Diese ist eine eher unelegante Code-Verdopplung -- hier sogar eine Verdreifachung.
+      Für den Produktiveinsatz lohnt es sich, darüber nachzudenken,
+      wie man diese vermeiden kann, ohne gleichzeitig an Effizienz einzubüßen.
+      Hierfür käme z.\,B.\ ein Präprozessor-Makro in Frage.
+      Für die Lösung der Übungsaufgabe wird dies hingegen nicht verlangt.)
+
+    \item
+      \textbf{Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte.
+      Damit können Sie sich gleichzeitig von der Bedingung lösen,
+      daß die Länge des Arrays ein Vielfaches von 8 sein muß.}
+
+      Siehe: \gitfile{hp}{2023ws/20231214}{loesung-1-3.c}
+
+      Um weitere Code-Verdopplungen zu vermeiden,
+      führen wir eine Funktion \lstinline{check_index()} ein,
+      die alle Prüfungen durchführt.
+
+      Wenn die Länge des Arrays kein Vielfaches von 8 ist,
+      wird das letzte Byte nicht vollständig genutzt.
+      Die einzige Schwierigkeit besteht darin, die korrekte Anzahl von Bytes
+      zu ermitteln, nämlich die Länge dividiert durch 8, aber nicht ab-, sondern
+      aufgerundet. Am elegantesten geht dies durch vorherige Addition von 7:
+      \lstinline{#define BYTES ((LENGTH + 7) / 8)}.
+      Es ist aber auch zulässig, die Anzahl der Bytes mit Hilfe einer
+      \lstinline{if}-Anweisung zu ermitteln: Länge durch 8 teilen und abrunden;
+      falls die Division nicht glatt aufging, um 1 erhöhen.
+
+    \item
+      \textbf{Gehen Sie nun von einem statischen zu einem dynamischen Array über,
+      und implementieren sie die Funktionen \lstinline{bit_array_init()},
+      \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}.}
+
+      Siehe: \gitfile{hp}{2023ws/20231214}{loesung-1-4.c}.
+      Damit ist die Aufgabe gelöst.
+
+      Aus den Präprozessor-Konstanten \lstinline{LENGTH} und \lstinline{BYTES}
+      werden nun globale \lstinline{int}-Variable.
+      Die Funktion \lstinline{bit_array_init()} berechnet die korrekten Werte
+      für diese Variablen und legt das Array mittels \lstinline{malloc()} dynamisch
+      an. Eine Größenänderung des Arrays erfolgt mittels \lstinline{realloc()},
+      das Freigeben mittels \lstinline{free()}.
+
+      Das Programm setzt Variable, die aktuell nicht verwendet werden,
+      auf den Wert \lstinline{0} bzw.\ \lstinline{NULL}.
+      Dies ermöglicht es der Funktion \lstinline{check_index()},
+      auch zu prüfen, ob das Array vorher korrekt mit \lstinline{bit_array_init()}
+      erzeugt wurde -- oder ob es vielleicht schon wieder mit
+      \lstinline{bit_array_done()} freigegeben wurde.
+
+  \end{itemize}
+
+  \clearpage
+
+  \exercise{Objektorientierte Tier-Datenbank}
+
+  Das unten dargestellte Programm (Datei: \gitfile{hp}{2023ws/20231214}{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 in Rot dargestellten Ersetzungen vor\\
+  (Datei: \gitfile{hp}{2023ws/20231214}{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}{2023ws/20231214}{loesung-2d-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}{2023ws/20231214}{loesung-2d-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}{2023ws/20231214}{loesung-2d-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}{2023ws/20231214}{loesung-2e.c}.
+      
+      Diese Lösung basiert auf \gitfile{hp}{2023ws/20231214}{loesung-2d-2.c},
+      da diese bereits weniger explizite Typumwandlungen enthält
+      als \gitfile{hp}{2023ws/20231214}{loesung-2d-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}{2023ws/20231214}{loesung-2f.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}{2023ws/20231214}{loesung-2g.c}.
+
+  \end{itemize}
+
+\end{document}
diff --git a/20231214/hp-uebung-20231214.pdf b/20231214/hp-uebung-20231214.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..1d3c327e01e726f080d97393780326be8dfe5505
Binary files /dev/null and b/20231214/hp-uebung-20231214.pdf differ
diff --git a/20231214/hp-uebung-20231214.tex b/20231214/hp-uebung-20231214.tex
new file mode 100644
index 0000000000000000000000000000000000000000..406fb68367ba09e7b9b0d772ecc5f90e051f95cc
--- /dev/null
+++ b/20231214/hp-uebung-20231214.tex
@@ -0,0 +1,253 @@
+% hp-uebung-20231214.pdf - Exercises on Low-Level Programming / Applied Computer Sciences
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  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: dynamisches Bit-Array, objektorientierte Tier-Datenbank
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{gensymb}
+
+\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C}
+\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C}
+
+\begin{document}
+
+  \thispagestyle{empty}
+
+  \section*{Hardwarenahe Programmierung\\
+            Übungsaufgaben -- 14.\ Dezember 2023}
+
+  Diese Übung enthält Punkteangaben wie in einer Klausur.
+  Um zu "`bestehen"', müssen Sie innerhalb von 80 Minuten
+  unter Verwendung ausschließlich zugelassener Hilfsmittel
+  14 Punkte (von insgesamt \totalpoints) erreichen.
+
+  \exercise{Dynamisches Bit-Array}
+
+  Schreiben Sie die folgenden Funktionen zur Verwaltung eines dynamischen Bit-Arrays:
+  \begin{itemize}
+    \item
+      \lstinline{void bit_array_init (int n)}\\
+      Das Array initialisieren, so daß man \lstinline{n} Bits darin speichern kann.\\
+      Die Array-Größe \lstinline{n} ist keine Konstante, sondern erst im laufenden Programm bekannt.\\
+      Die Bits sollen auf den Anfangswert 0 initialisiert werden.
+    \item
+      \lstinline{void bit_array_set (int i, int value)}\\
+      Das Bit mit dem Index \lstinline{i} auf den Wert \lstinline{value} setzen.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen;
+      der Wert \lstinline{value} darf 1 oder 0 sein.
+    \item
+      \lstinline{void bit_array_flip (int i)}\\
+      Das Bit mit dem Index \lstinline{i} auf den entgegengesetzten Wert setzen,\\
+      also auf 1, wenn er vorher 0 ist, bzw.\ auf 0, wenn er vorher 1 ist.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
+    \item
+      \lstinline{int bit_array_get (int i)}\\
+      Den Wert des Bit mit dem Index \lstinline{i} zurückliefern.\\
+      Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
+    \item
+      \lstinline{void bit_array_resize (int new_n)}\\
+      Die Größe des Arrays auf \lstinline{new_n} Bits ändern.\\
+      Dabei soll der Inhalt des Arrays, soweit er in die neue Größe paßt, erhalten bleiben.\\
+      Neu hinzukommende Bits sollen auf 0 initialisiert werden.
+    \item
+      \lstinline{void bit_array_done (void)}\\
+      Den vom Array belegten Speicherplatz wieder freigeben.
+  \end{itemize}
+  Bei Bedarf dürfen Sie den Funktionen zusätzliche Parameter mitgeben,
+  beispielsweise um mehrere Arrays parallel verwalten zu können.
+  (In der objektorientierten Programmierung wäre dies der implizite Parameter \lstinline{this},
+  der auf die Objekt-Struktur zeigt.)
+
+  Die Bits sollen möglichst effizient gespeichert werden,
+  z.\,B.\ jeweils 8 Bits in einer \lstinline{uint8_t}-Variablen.
+
+  Die Funktionen sollen möglichst robust sein,
+  d.\,h.\ das Programm darf auch bei unsinnigen Parameterwerten nicht abstürzen,
+  sondern soll eine Fehlermeldung ausgeben.
+
+  \medskip
+
+  Die folgenden \textbf{Hinweise} beschreiben
+  einen möglichen Weg, die Aufgabe zu lösen.
+  Es seht Ihnen frei, die Aufgabe auch auf andere Weise zu lösen.
+  \begin{itemize}
+    \item
+      Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat,
+      und schreiben Sie zunächst nur die Funktionen
+      \lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und
+      \lstinline{bit_array_get()}.
+    \item
+      Verallgemeinern Sie nun auf eine konstante Länge,
+      bei der es sich um ein Vielfaches von 8 handelt.
+    \item
+      Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte.
+      Damit können Sie sich gleichzeitig von der Bedingung lösen,
+      daß die Länge des Arrays ein Vielfaches von 8 sein muß.
+    \item
+      Gehen Sie nun von einem statischen zu einem dynamischen Array über,
+      und implementieren Sie die Funktionen \lstinline{bit_array_init()},
+      \lstinline{bit_array_done()} und \lstinline{bit_array_resize()}.
+  \end{itemize}
+
+  \points{14}
+
+  \medskip
+
+  (Hinweis für die Klausur:
+  Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.)
+
+  \clearpage
+  \exercise{Objektorientierte Tier-Datenbank}
+
+  Das unten dargestellte Programm (Datei: \gitfile{hp}{2023ws/20231214}{aufgabe-2a.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 in Rot dargestellten Ersetzungen vor
+  (Datei: \gitfile{hp}{2023ws/20231214}{aufgabe-2b.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/20231214/landau-symbols-2.pdf b/20231214/landau-symbols-2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..6b458b6efd8e274824a6dfcaabc4b9c27d196dc4
--- /dev/null
+++ b/20231214/landau-symbols-2.pdf
@@ -0,0 +1 @@
+../common/landau-symbols-2.pdf
\ No newline at end of file
diff --git a/20231214/landau-symbols-3.pdf b/20231214/landau-symbols-3.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..46efa409b35ff5df763c744a423599cba515d886
--- /dev/null
+++ b/20231214/landau-symbols-3.pdf
@@ -0,0 +1 @@
+../common/landau-symbols-3.pdf
\ No newline at end of file
diff --git a/20231214/landau-symbols.pdf b/20231214/landau-symbols.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..ca145425bf07439c680632aa0663f84be601a565
--- /dev/null
+++ b/20231214/landau-symbols.pdf
@@ -0,0 +1 @@
+../common/landau-symbols.pdf
\ No newline at end of file
diff --git a/20231214/loesung-1-1.c b/20231214/loesung-1-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..11ad08a28a2c16e645e4b55c1b0f4556246fd692
--- /dev/null
+++ b/20231214/loesung-1-1.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdint.h>
+
+uint8_t buffer = 0;
+
+void bit_array_set (int i, int value)
+{
+  uint8_t mask = 1 << i;
+  if (value)
+    buffer |= mask;
+  else
+    buffer &= ~mask;
+}
+
+void bit_array_flip (int i)
+{
+  uint8_t mask = 1 << i;
+  buffer ^= mask;
+}
+
+int bit_array_get (int i)
+{
+  uint8_t mask = 1 << i;
+  if (buffer & mask)
+    return 1;
+  else
+    return 0;
+}
+
+void output (void)
+{
+  for (int i = 0; i < 8; i++)
+    {
+      if (i % 4 == 0)
+        printf (" ");
+      printf ("%d", bit_array_get (i));
+    }
+  printf ("\n");
+}
+
+int main (void)
+{
+  output ();
+  bit_array_set (2, 1);
+  output ();
+  bit_array_flip (7);
+  output ();
+  bit_array_set (2, 0);
+  output ();
+}
diff --git a/20231214/loesung-1-2.c b/20231214/loesung-1-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..e510904b033cf7d55737cee55ad08ecb9510f324
--- /dev/null
+++ b/20231214/loesung-1-2.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#define LENGTH 32
+
+uint8_t buffer[LENGTH / 8] = { 0, 0, 0, 0 };
+
+void bit_array_set (int i, int value)
+{
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (value)
+    buffer[byte_index] |= mask;
+  else
+    buffer[byte_index] &= ~mask;
+}
+
+void bit_array_flip (int i)
+{
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  buffer[byte_index] ^= mask;
+}
+
+int bit_array_get (int i)
+{
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (buffer[byte_index] & mask)
+    return 1;
+  else
+    return 0;
+}
+
+void output (void)
+{
+  for (int i = 0; i < LENGTH; i++)
+    {
+      if (i % 4 == 0)
+        printf (" ");
+      printf ("%d", bit_array_get (i));
+    }
+  printf ("\n");
+}
+
+int main (void)
+{
+  output ();
+  bit_array_set (12, 1);
+  output ();
+  bit_array_flip (31);
+  output ();
+  bit_array_set (12, 0);
+  output ();
+}
diff --git a/20231214/loesung-1-3.c b/20231214/loesung-1-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..4177464aebf41205169a6bb02b27ac972e3a4f4e
--- /dev/null
+++ b/20231214/loesung-1-3.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <error.h>
+
+#define LENGTH 29
+#define BYTES ((LENGTH + 7) / 8)
+
+uint8_t buffer[BYTES] = { 0, 0, 0, 0 };
+
+void check_index (int i)
+{
+  if (i < 0 || i >= LENGTH)
+    error (1, 0, "index %d out of range (0, ..., %d)", i, LENGTH - 1);
+}
+
+void bit_array_set (int i, int value)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (value)
+    buffer[byte_index] |= mask;
+  else
+    buffer[byte_index] &= ~mask;
+}
+
+void bit_array_flip (int i)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  buffer[byte_index] ^= mask;
+}
+
+int bit_array_get (int i)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (buffer[byte_index] & mask)
+    return 1;
+  else
+    return 0;
+}
+
+void output (void)
+{
+  for (int i = 0; i < LENGTH; i++)
+    {
+      if (i % 4 == 0)
+        printf (" ");
+      printf ("%d", bit_array_get (i));
+    }
+  printf ("\n");
+}
+
+int main (void)
+{
+  output ();
+  bit_array_set (12, 1);
+  output ();
+  bit_array_flip (28);
+  output ();
+  bit_array_set (12, 0);
+  output ();
+  bit_array_flip (31);
+  output ();
+}
diff --git a/20231214/loesung-1-4.c b/20231214/loesung-1-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..1930580aae8e8b24528852d1dacf58051f6bd6cc
--- /dev/null
+++ b/20231214/loesung-1-4.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <error.h>
+#include <stdlib.h>
+
+int length = 0;
+int bytes = 0;
+uint8_t *buffer = NULL;
+
+void bit_array_init (int n)
+{
+  length = n;
+  bytes = (length + 7) / 8;
+  if (buffer)
+    free (buffer);
+  buffer = malloc (bytes * sizeof (uint8_t));
+  for (int i = 0; i < bytes; i++)
+    buffer[i] = 0;
+}
+
+void bit_array_resize (int new_n)
+{
+  length = new_n;
+  bytes = (length + 7) / 8;
+  buffer = realloc (buffer, bytes * sizeof (uint8_t));
+}
+
+void bit_array_done (void)
+{
+  free (buffer);
+  buffer = NULL;
+  length = 0;
+  bytes = 0;
+}
+
+void check_index (int i)
+{
+  if (!buffer)
+    error (1, 0, "array not initialised");
+  if (i < 0 || i >= length)
+    error (1, 0, "index %d out of range (0, ..., %d)", i, length - 1);
+}
+
+void bit_array_set (int i, int value)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (value)
+    buffer[byte_index] |= mask;
+  else
+    buffer[byte_index] &= ~mask;
+}
+
+void bit_array_flip (int i)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  buffer[byte_index] ^= mask;
+}
+
+int bit_array_get (int i)
+{
+  check_index (i);
+  int byte_index = i / 8;
+  int bit_index = i % 8;
+  uint8_t mask = 1 << bit_index;
+  if (buffer[byte_index] & mask)
+    return 1;
+  else
+    return 0;
+}
+
+void output (void)
+{
+  for (int i = 0; i < length; i++)
+    {
+      if (i % 4 == 0)
+        printf (" ");
+      printf ("%d", bit_array_get (i));
+    }
+  printf ("\n");
+}
+
+int main (void)
+{
+  bit_array_init (29);
+  output ();
+  bit_array_set (12, 1);
+  output ();
+  bit_array_flip (28);
+  output ();
+  bit_array_set (12, 0);
+  output ();
+  bit_array_flip (31);
+  output ();
+  bit_array_done ();
+}
diff --git a/20231214/loesung-2d-0f.c b/20231214/loesung-2d-0f.c
new file mode 100644
index 0000000000000000000000000000000000000000..04b2d3e8956f4790b3f2ffdf3a314994c640513e
--- /dev/null
+++ b/20231214/loesung-2d-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/20231214/loesung-2d-1.c b/20231214/loesung-2d-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..349523a7d99e33ba81094ffbc8907773b5a3a251
--- /dev/null
+++ b/20231214/loesung-2d-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/20231214/loesung-2d-2.c b/20231214/loesung-2d-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f831a75eda1f3e784c8e6c1f24a83d9d6b55ee6c
--- /dev/null
+++ b/20231214/loesung-2d-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/20231214/loesung-2e.c b/20231214/loesung-2e.c
new file mode 100644
index 0000000000000000000000000000000000000000..b984d9253b9c379a88f0fc0ca130c88c3103f8f3
--- /dev/null
+++ b/20231214/loesung-2e.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/20231214/loesung-2f.c b/20231214/loesung-2f.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b949e6365fc3839e6adc7661e0f8b4dd0c059df
--- /dev/null
+++ b/20231214/loesung-2f.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/20231214/loesung-2g.c b/20231214/loesung-2g.c
new file mode 100644
index 0000000000000000000000000000000000000000..b453a52dbe0ef27399255819808b3f6e562ba3ef
--- /dev/null
+++ b/20231214/loesung-2g.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/20231214/logo-hochschule-bochum-cvh-text-v2.pdf b/20231214/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20231214/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/20231214/logo-hochschule-bochum.pdf b/20231214/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20231214/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20231214/pgscript.sty b/20231214/pgscript.sty
new file mode 120000
index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b
--- /dev/null
+++ b/20231214/pgscript.sty
@@ -0,0 +1 @@
+../common/pgscript.sty
\ No newline at end of file
diff --git a/20231214/pgslides.sty b/20231214/pgslides.sty
new file mode 120000
index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64
--- /dev/null
+++ b/20231214/pgslides.sty
@@ -0,0 +1 @@
+../common/pgslides.sty
\ No newline at end of file