diff --git a/20231102/Makefile-1 b/20231102/Makefile-1 new file mode 100644 index 0000000000000000000000000000000000000000..bfc1b10a929f22a8c2f4f0cf0368c78db14ad0b0 --- /dev/null +++ b/20231102/Makefile-1 @@ -0,0 +1,8 @@ +philosophy: philosophy.o answer.o + gcc philosophy.o answer.o -o philosophy + +answer.o: answer.c answer.h + gcc -Wall -O answer.c -c + +philosophy.o: philosophy.c answer.h + gcc -Wall -O philosophy.c -c diff --git a/20231102/Makefile-2 b/20231102/Makefile-2 new file mode 100644 index 0000000000000000000000000000000000000000..60aab7c7d51b28879c41e8590ab422e9edfadee5 --- /dev/null +++ b/20231102/Makefile-2 @@ -0,0 +1,16 @@ +TARGET = philosophy +OBJECTS = philosophy.o answer.o +HEADERS = answer.h +CFLAGS = -Wall -O + +$(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + +answer.o: answer.c $(HEADERS) + gcc $(CFLAGS) answer.c -c + +philosophy.o: philosophy.c $(HEADERS) + gcc $(CFLAGS) philosophy.c -c + +clean: + rm -f $(OBJECTS) $(TARGET) diff --git a/20231102/Makefile-3 b/20231102/Makefile-3 new file mode 100644 index 0000000000000000000000000000000000000000..0ac355bfddfd237fe0f1b5062c5a242ab0d3e97e --- /dev/null +++ b/20231102/Makefile-3 @@ -0,0 +1,13 @@ +TARGET = philosophy +OBJECTS = philosophy.o answer.o +HEADERS = answer.h +CFLAGS = -Wall -O + +$(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + +%.o: %.c $(HEADERS) + gcc $(CFLAGS) $< -c + +clean: + rm -f $(OBJECTS) $(TARGET) diff --git a/20231102/aufgabe-3.c b/20231102/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..9ae72941b931c04f3c380cb3bbcd64bec7f08c20 --- /dev/null +++ b/20231102/aufgabe-3.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <string.h> + +void insert_into_string (char src, char *target, int pos) +{ + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; +} + +int main (void) +{ + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; +} diff --git a/20231102/hp-20231102.pdf b/20231102/hp-20231102.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bec0c954a377bc13efe2cc1f7a79aded717ef2c0 Binary files /dev/null and b/20231102/hp-20231102.pdf differ diff --git a/20231102/hp-20231102.tex b/20231102/hp-20231102.tex new file mode 100644 index 0000000000000000000000000000000000000000..435fb26e793f7e09ef15222e168ed674fad161a2 --- /dev/null +++ b/20231102/hp-20231102.tex @@ -0,0 +1,801 @@ +% hp-20231102.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: Bibliotheken + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{pdftricks} +\usepackage{tikz} + +\begin{psinputs} + \usepackage[utf8]{inputenc} + \usepackage[german]{babel} + \usepackage[T1]{fontenc} + \usepackage{helvet} + \renewcommand*\familydefault{\sfdefault} + \usepackage{pstricks,pst-grad} +\end{psinputs} + +\newcommand{\redurl}[1]{\href{#1}{\color{red}\nolinkurl{#1}}} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{2.\ November 2023} + +\begin{document} + +\maketitleframe + +%\date{\begin{picture}(0,0) +% \color{red} +% \put(0.65,1.05){\makebox(0,0)[t]{$\underbrace{\rule{1.45cm}{0pt}}_{% +% \mbox{\emph{rerum naturalium\/} = der natürlichen Dinge (lat.)}}$}} +% \put(1.65,-3){\makebox(0,0)[bl]{\redurl{https://www.peter.gerwinski.de/physik/}}} +% \end{picture}% +% 12.\ Oktober 2023} +% +%\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} + \begin{itemize} + \vspace{-1.5\smallskipamount} + \item[\dots] + \item[2.11] Arrays und Strings + \item[2.12] Strukturen + \item[2.13] Dateien und Fehlerbehandlung + \item[2.14] Parameter des Hauptprogramms + \color{medgreen} + \item[2.15] String-Operationen + \end{itemize} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \color{medgreen} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \color{orange} + \item[3.4] Callbacks + \color{red} + \item[3.5] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\section{Einführung} +\section{Einführung in C} +\setcounter{subsection}{14} +\subsection{String-Operationen} + +\begin{frame}[fragile] + + \showsubsection + +% \vspace*{-0.4cm} + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char hello[] = "Hello, world!\n"; + + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + printf ("%s\n", hello + 7); + printf ("%zd\n", strlen (hello + 7)); + + hello[5] = 0; + printf ("%s\n", hello); + printf ("%zd\n", strlen (hello)); + + return 0; + } + \end{lstlisting} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + +% \vspace*{-0.4cm} + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char *anton = "Anton"; + char *zacharias = "Zacharias"; + + printf ("%d\n", strcmp (anton, zacharias)); + printf ("%d\n", strcmp (zacharias, anton)); + printf ("%d\n", strcmp (anton, anton)); + + char buffer[100] = "Huber "; + strcat (buffer, anton); + printf ("%s\n", buffer); + + return 0; + } + \end{lstlisting} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + +% \vspace*{-0.4cm} + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + sprintf (buffer, "Die Antwort lautet: %d", 42); + printf ("%s\n", buffer); + + char *answer = strstr (buffer, "Antwort"); + printf ("%s\n", answer); + printf ("found at: %zd\n", answer - buffer); + + return 0; + } + \end{lstlisting} + \vspace*{-1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + +% \vspace*{-0.4cm} + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + int main (void) + { + char buffer[100] = ""; + snprintf (buffer, 100, "Die Antwort lautet: %d", 42); + printf ("%s\n", buffer); + + char *answer = strstr (buffer, "Antwort"); + printf ("%s\n", answer); + printf ("found at: %zd\n", answer - buffer); + + return 0; + } + \end{lstlisting} + +\end{frame} + +\begin{frame} + + \showsection + + Sprachelemente weitgehend komplett + + \bigskip + Es fehlen: + \begin{itemize} + \item + Ergänzungen (z.\,B.\ ternärer Operator, \lstinline{union}, \lstinline{unsigned}, \lstinline{volatile}) + \item + Bibliotheksfunktionen (z.\,B.\ \lstinline{malloc()}) + \arrowitem + werden eingeführt, wenn wir sie brauchen + \bigskip + \item + Konzepte (z.\,B.\ rekursive Datenstrukturen, Klassen selbst bauen) + \arrowitem + werden eingeführt, wenn wir sie brauchen, oder: + \arrowitem + Literatur\\[\smallskipamount] + (z.\,B.\ Wikibooks: C-Programmierung,\\ + Dokumentation zu Compiler und Bibliotheken) + \bigskip + \item + Praxiserfahrung + \arrowitem + Übung und Praktikum: nur Einstieg + \arrowitem + selbständig arbeiten + \end{itemize} +\end{frame} + +\section{Bibliotheken} +\subsection{Der Präprozessor} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \lstinline{#include}: %\pause: + Text einbinden + \begin{itemize} +% \pause + \item + \lstinline{#include <stdio.h>}: Standard-Verzeichnisse -- Standard-Header +% \pause + \item + \lstinline{#include "answer.h"}: auch aktuelles Verzeichnis -- eigene Header + \end{itemize} + +% \pause + \bigskip + + \lstinline{#define SIX 6}: Text ersetzen lassen -- Konstante definieren + \begin{itemize} +% \pause + \item + Kein Semikolon! +% \pause + \item + Berechnungen in Klammern setzen:\\ + \lstinline{#define SIX (1 + 5)} +% \pause + \item + Konvention: Großbuchstaben + \end{itemize} + +\end{frame} + +\subsection{Bibliotheken einbinden} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + Inhalt der Header-Datei: externe Deklarationen + +% \pause + \smallskip + \lstinline{extern int answer (void);} + +% \pause + \smallskip + \lstinline{extern int printf (__const char *__restrict __format, ...);} + +% \pause + \bigskip + Funktion wird "`anderswo"' definiert + \begin{itemize} +% \pause + \item + separater C-Quelltext: mit an \lstinline[style=terminal]{gcc} übergeben +% \pause + \item + Zusammenfügen zu ausführbarem Programm durch den \newterm{Linker} +% \pause + \item + vorcompilierte Bibliothek: \lstinline[style=terminal]{-lfoo}\\ +% \pause + = Datei \file{libfoo.a} in Standard-Verzeichnis + \end{itemize} + +\end{frame} + +\subsection{Bibliothek verwenden (Beispiel: GTK)} + +\begin{frame}[fragile] + + \showsubsection + + \begin{itemize} + \item + \lstinline{#include <gtk/gtk.h>} + \pause + \smallskip + \item + Mit \lstinline[style=cmd]{pkg-config --cflags --libs gtk4} erfährt man,\\ + welche Optionen und Bibliotheken man an \lstinline[style=cmd]{gcc} + übergeben muß\alt<4->{.}{:} + \pause + \begin{onlyenv}<3> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡pkg-config --cflags --libs gtk4¿ + -I/usr/include/gtk-4.0 -I/usr/include/pango-1.0 -I/usr/ + include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/i + nclude -I/usr/include/harfbuzz -I/usr/include/freetype2 + -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/ + include/blkid -I/usr/include/fribidi -I/usr/include/cai + ro -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2. + 0 -I/usr/include/x86_64-linux-gnu -I/usr/include/graphe + ne-1.0 -I/usr/lib/x86_64-linux-gnu/graphene-1.0/include + -mfpmath=sse -msse -msse2 -pthread -lgtk-4 -lpangocairo + -1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-go + bject -lcairo -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -l + glib-2.0 + \end{lstlisting} + \vspace*{-3cm} + \end{onlyenv} + \pause + \arrowitem + Compiler-Aufruf: + \begin{onlyenv}<4> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡gcc -Wall -O hello-gtk.c -I/usr/include/gtk-4.0 -I/u + sr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib + /x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfb + uzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I + /usr/include/libmount -I/usr/include/blkid -I/usr/inclu + de/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 + -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-lin + ux-gnu -I/usr/include/graphene-1.0 -I/usr/lib/x86_64-li + nux-gnu/graphene-1.0/include -mfpmath=sse -msse -msse2 + -pthread -lgtk-4 -lpangocairo -1.0 -lpango-1.0 -lharfbu + zz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene- + 1.0 -lgio-2.0 -lgobject-2.0 -l glib-2.0 -o hello-gtk¿ + \end{lstlisting} + \vspace*{-2cm} + \end{onlyenv} + \begin{onlyenv}<5-> + \begin{lstlisting}[style=terminal,gobble=10] + $ ¡gcc -Wall -O hello-gtk.c $(pkg-config --cflags --libs + gtk4) -o hello-gtk¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<5> + \begin{picture}(0,0)(0.3,0.3) + \color{red} + \put(6.6,-0.6){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(3,1.5);}}} + \put(6.3,-0.7){\makebox(0,0)[t]{\shortstack{\strut Optionen:\\ + \strut u.\,a.\ viele Include-Verzeichnisse:\\ + \lstinline[style=cmd]{-I/usr/include/gtk-4.0}}}} + \put(10.0,-2.1){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(1.5,3);}}} + \put(10.3,-2.2){\makebox(0,0)[t]{\shortstack{\strut Bibliotheken:\\ + \strut u.\,a.\ \lstinline[style=cmd]{-lgtk-4}}}} + \end{picture} + \end{onlyenv} + \pause + \pause + \item + Auf manchen Plattformen kommt es auf die Reihenfolge an: + \begin{lstlisting}[style=terminal,gobble=8] + $ ¡gcc -Wall -O $(pkg-config --cflags gtk4) \ + hello-gtk.c $(pkg-config --libs gtk4) \ + -o hello-gtk¿ + \end{lstlisting} + (Backslash = "`Es geht in der nächsten Zeile weiter."') + \end{itemize} + +\end{frame} + +\subsection{Callbacks} + +\begin{frame}[fragile] + + \showsubsection + + Selbst geschriebene Funktion übergeben: \newterm{Callback} + + \bigskip + + \begin{lstlisting}[xleftmargin=1em] + static void hello (GtkWidget *this, gpointer user_data) + { + char *world = user_data; + printf ("Hello, %s!\n", world); + } + + ... + + g_signal_connect (button, "clicked", G_CALLBACK (hello), "world"); + \end{lstlisting} + + \medskip + + \begin{itemize} + \arrowitem + GTK ruft immer dann, wenn der Button betätigt wurde,\\ + die Funktion \lstinline{hello} auf. + \end{itemize} + + \pause + \begin{picture}(0,0)(1.1,0.8) + \color{red} + \put(9.7,5.1){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.3,0.5);}}} + \put(10.0,5.0){\makebox(0,0)[t]{\shortstack{\strut optionale Zusatzinformationen\\ + \strut für hello(), hier ein String\\ + \strut oft ein Zeiger auf ein struct}}} + \put(10.5,3.5){\makebox(0,0)[tl]{\tikz{\draw[-latex](0,0)--(0.3,-0.5);}}} + \end{picture} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Selbst geschriebene Funktion übergeben: \newterm{Callback} + + \bigskip + + \begin{lstlisting}[xleftmargin=1em] + static void draw (GtkDrawingArea *drawing_area, cairo_t *c, + int width, int height, gpointer user_data) + { + /* Zeichenbefehle */ + ... + } + + ... + + gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), + draw, NULL, NULL); + \end{lstlisting} + + \medskip + + \begin{itemize} + \arrowitem + GTK ruft immer dann, wenn es etwas zu zeichnen gibt,\\ + die Funktion \lstinline{draw} auf. + \end{itemize} + + \pause + \begin{picture}(0,0) + \color{red} + \put(10.0,4.9){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.3,0.9);}}} + \put(10.0,4.8){\makebox(0,0)[t]{\shortstack{\strut repräsentiert den\\ + \strut Bildschirm, auf den\\ + \strut gezeichnet werden soll}}} + \end{picture} + +\end{frame} + +\iffalse + +\begin{frame}[fragile] + + \showsubsection + + Selbst geschriebene Funktion übergeben: \newterm{Callback} + + \bigskip + + \begin{lstlisting}[xleftmargin=1em] + gboolean timer (GtkWidget *widget) + { + /* Rechenbefehle */ + ... + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; + } + + ... + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + \end{lstlisting} + + \medskip + + \begin{itemize} + \arrowitem + GTK+ ruft nach 50 Millisekunden + die Funktion \lstinline{timer} auf. + \end{itemize} + + \pause + \begin{picture}(0,0)(-0.07,0.2) + \color{red} + \put(9.7,6.7){\makebox(0,0)[t]{\shortstack{\strut Dieser Bereich soll\\ + \strut neu gezeichnet werden.}}} + \put(9.7,5.7){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.8);}}} + \pause + \put(4.3,3.2){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.7,0.6);}}} + \put(4.3,3.1){\makebox(0,0)[t]{\shortstack{\strut In weiteren 50 Millisekunden soll\\ + \strut die Funktion erneut aufgerufen werden.}}} + \pause + \put(9.3,2.9){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-3.3,0.9);}}} + \put(9.8,2.8){\makebox(0,0)[t]{\shortstack{\strut Explizite Typumwandlung\\ + \strut eines Zeigers (später)}}} + \end{picture} + +\end{frame} + +\fi + +\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} + \begin{itemize} + \vspace{-1.5\smallskipamount} + \item[\dots] + \item[2.11] Arrays und Strings + \item[2.12] Strukturen + \item[2.13] Dateien und Fehlerbehandlung + \item[2.14] Parameter des Hauptprogramms + \color{medgreen} + \item[2.15] String-Operationen + \end{itemize} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \color{medgreen} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \color{orange} + \item[3.4] Callbacks + \color{red} + \item[3.5] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \vspace*{-\smallskipamount} + \item[\textbf{\dots}] +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\subsection{Projekt organisieren: make} + +\begin{frame}[fragile] + + \showsubsection + \begin{itemize} + \item + \only<4->{explizite und implizite} Regeln + \begin{onlyenv}<2> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + philosophy: philosophy.o answer.o + gcc philosophy.o answer.o -o philosophy + + answer.o: answer.c answer.h + gcc -Wall -O answer.c -c + + philosophy.o: philosophy.c answer.h + gcc -Wall -O philosophy.c -c + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<4> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + TARGET = philosophy + OBJECTS = philosophy.o answer.o + HEADERS = answer.h + CFLAGS = -Wall -O + + $(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + + %.o: %.c $(HEADERS) + gcc $(CFLAGS) $< -c + + clean: + rm -f $(OBJECTS) $(TARGET) + \end{lstlisting} + \end{onlyenv} + \item + Makros + \begin{onlyenv}<3> + \smallskip + \begin{lstlisting}[language=make,gobble=10] + TARGET = philosophy + OBJECTS = philosophy.o answer.o + HEADERS = answer.h + CFLAGS = -Wall -O + + $(TARGET): $(OBJECTS) + gcc $(OBJECTS) -o $(TARGET) + + answer.o: answer.c $(HEADERS) + gcc $(CFLAGS) answer.c -c + + philosophy.o: philosophy.c $(HEADERS) + gcc $(CFLAGS) philosophy.c -c + + clean: + rm -f $(OBJECTS) $(TARGET) + \end{lstlisting} + \vspace*{-1cm} + \end{onlyenv} + \begin{onlyenv}<5-> + \smallskip + \arrowitem + 3 Sprachen: C, Präprozessor, make + \end{onlyenv} + \end{itemize} + +\end{frame} + +\section{Hardwarenahe Programmierung} +\subsection{Bit-Operationen} +\subsubsection{Zahlensysteme} + +\begin{frame}[fragile] + + \showsection + \vspace*{-\smallskipamount} + \showsubsection + \vspace*{-\medskipamount} + \showsubsubsection + + \begin{tabular}{rlrl} + Basis & Name & Beispiel & Anwendung \\[\smallskipamount] + 2 & Binärsystem & 1\,0000\,0011 & Bit-Operationen \\ + 8 & Oktalsystem & \lstinline,0403, & Dateizugriffsrechte (Unix) \\ + 10 & Dezimalsystem & \lstinline,259, & Alltag \\ + 16 & Hexadezimalsystem & \lstinline,0x103, & Bit-Operationen \\ + 256 & (keiner gebräuchlich) & 0.0.1.3 & IP-Adressen (IPv4) + \end{tabular} + + \bigskip + + \begin{itemize} + \item + Computer rechnen im Binärsystem. + \item + Für viele Anwendungen (z.\,B.\ I/O-Ports, Grafik, \dots) ist es notwendig,\\ + Bits in Zahlen einzeln ansprechen zu können. + \end{itemize} + +\end{frame} + +\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} + +\begin{frame}[fragile] + + \showsubsubsection + + C-Datentypen für Bit-Operationen: + \smallskip\par + \lstinline{#include <stdint.h>} + \medskip\par + \begin{tabular}{lllll} + & 8 Bit & 16 Bit & 32 Bit & 64 Bit \\ + mit Vorzeichen & \lstinline,int8_t, + & \lstinline,int16_t, + & \lstinline,int32_t, + & \lstinline,int64_t, \\ + ohne Vorzeichen & \lstinline,uint8_t, + & \lstinline,uint16_t, + & \lstinline,uint32_t, + & \lstinline,uint64_t, + \end{tabular} + + \bigskip + \bigskip + + Ausgabe: + \smallskip\par + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + #include <inttypes.h> + ... + uint64_t x = 42; + printf ("Die Antwort lautet: %" PRIu64 "\n", x); + \end{lstlisting} + +\end{frame} + +\end{document} diff --git a/20231102/hp-musterloesung-20231102.pdf b/20231102/hp-musterloesung-20231102.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c4d6f358ca66162c954859b82ddfd5a133ae99a4 Binary files /dev/null and b/20231102/hp-musterloesung-20231102.pdf differ diff --git a/20231102/hp-musterloesung-20231102.tex b/20231102/hp-musterloesung-20231102.tex new file mode 100644 index 0000000000000000000000000000000000000000..c08babb5a37b01520a2f1ea4a7ea064831186c5b --- /dev/null +++ b/20231102/hp-musterloesung-20231102.tex @@ -0,0 +1,492 @@ +% hp-musterloesung-20231102.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: Zahlensysteme, Ausgabe von Hexadezimalzahlen, Einfügen in Strings + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\renewcommand{\breath}{\bigskip} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 2.\ November 2023} + + \exercise{Zahlensysteme} + + Wandeln Sie ohne Hilfsmittel + + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + 0010\,0000$_2$ + \item[(b)] + 42$_{16}$ + \item[(c)] + 17$_8$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + 0010\,0000$_2$ + \item[(e)] + 42$_{10}$ + \item[(f)] + 192.168.20.254$_{256}$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + 750$_8$ + \item[(h)] + 42$_{10}$ + \item[(i)] + AFFE$_{16}$ + \end{itemize} + \end{itemize} + \end{minipage} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + 750$_8$ \& 666$_8$ + \item[(k)] + A380$_{16}$ + B747$_{16}$ + \item[(l)] + AFFE$_{16} >> 1$ + \end{itemize} + + Die tiefgestellte Zahl steht für die Basis des Zahlensystems. + Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12} + + (In der Klausur sind Hilfsmittel zugelassen, + daher ist dies \emph{keine\/} typische Klausuraufgabe.) + + \solution + + Wandeln Sie ohne Hilfsmittel + + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + $0010\,0000_2 = 32_{10}$ + + Eine Eins mit fünf Nullen dahinter steht binär für $2^5 = 32$:\\ + mit $1$ anfangen und fünfmal verdoppeln. + \item[(b)] + $42_{16} = 4 \cdot 16 + 2 \cdot 1 = 64 + 2 = 66$ + \item[(c)] + $17_8 = 1 \cdot 8 + 7 \cdot 1 = 8 + 7 = 15$ + \end{itemize} + Umwandlung von und nach Dezimal ist immer rechenaufwendig. + Umwandlungen zwischen Binär, Oktal und Hexadezimal gehen ziffernweise + und sind daher wesentlich einfacher. + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + $0010\,0000_2 = 20_{16}$ + + Umwandlung von Binär nach Hexadezimal geht ziffernweise:\\ + Vier Binärziffern werden zu einer Hex-Ziffer. + \item[(e)] + $\rm 42_{10} = 32_{10} + 10_{10} = 20_{16} + A_{16} = 2A_{16}$ + \item[(f)] + $\rm 192.168.20.254_{256} = C0\,A8\,14\,FE_{16}$ + + Umwandlung von der Basis 256 nach Hexadezimal geht ziffernweise:\\ + Eine 256er-Ziffer wird zu zwei Hex-Ziffern. + + Da die 256er-Ziffern dezimal angegeben sind, + müssen wir viermal Dezimal nach Hexadezimal umwandeln. + Hierfür bieten sich unterschiedliche Wege an. + + $\rm 192_{10} = 128_{10} + 64_{10} = 1100\,0000_{2} = C0_{16}$ + + $\rm 168_{10} = 10_{10} \cdot 16_{10} + 8_{10} = A_{16} \cdot 10_{16} + 8_{16} = A8_{16}$ + + $20_{10} = 16_{10} + 4_{10} = 10_{16} + 4_{16} = 14$ + + $\rm 254_{10} = 255_{10} - 1_{10} = FF_{16} - 1_{16} = FE_{16}$ + \end{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + $750_8 = 111\,101\,000_2$ + + Umwandlung von Oktal nach Binär geht ziffernweise:\\ + Eine Oktalziffer wird zu drei Binärziffern. + \item[(h)] + $\rm 42_{10} = 2A_{16}$ (siehe oben) $= 0010\,1010_{16}$ + + Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\ + Eine Hex-Ziffer wird zu vier Binärziffern. + \item[(i)] + $\rm AFFE_{16} = 1010\,1111\,1111\,1110_2$ + + Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\ + Eine Hex-Ziffer wird zu vier Binärziffern. + \end{itemize} + \end{itemize} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + $750_8\,\&\,666_8 + = 111\,101\,000_2\,\&\,110\,110\,110_2 + = 110\,100\,000_2 + = 640_8$ + + Binäre Und-Operationen lassen sich am leichtesten + in binärer Schreibweise durchführen. + Umwandlung zwischen Oktal und Binär geht ziffernweise: + Eine Oktalziffer wird zu drei Binärziffern und umgekehrt. + + Mit etwas Übung funktionieren diese Operationen + auch direkt mit Oktalzahlen im Kopf. + + \item[(k)] + $\rm\phantom{+}A380_{16}$\\ + $\rm+\kern2ptB747_{16}$\\[-\medskipamount] + \rule{1.4cm}{0.5pt}\\ + $\rm 15AC7_{16}$ + \begin{picture}(0,0) + \put(-1.4,0.35){\mbox{\scriptsize\bf 1}} + \end{picture} + + Mit Hexadezimalzahlen (und Binär- und Oktal- und sonstigen Zahlen) + kann man genau wie mit Dezimalzahlen schriftlich rechnen. + Man muß nur daran denken, daß der "`Zehner"'-Überlauf nicht bei + $10_{10}$ stattfindet, sondern erst bei $10_{16} = 16_{10}$ + (hier: $\rm 8_{16} + 4_{16} = C_{16}$ und + $\rm 3_{16} + 7_{16} = A_{16}$, aber + $\rm A_{16} + B_{16} = 10_{10} + 11_{10} + = 21_{10} = 16_{10} + 5_{10} = 10_{16} + 5_{16} = 15_{16}$). + + \item[(l)] + $\rm AFFE_{16} >> 1 + = 1010\,1111\,1111\,1110_2 >> 1 + = 0101\,0111\,1111\,1111_2 + = 57FF_{16}$ + + Bit-Verschiebungen lassen sich am leichtesten + in binärer Schreibweise durchführen. + Umwandlung zwischen Hexadezimal und Binär geht ziffernweise: + Eine Hex-Ziffer wird zu vier Binärziffern und umgekehrt. + + Mit etwas Übung funktionieren diese Operationen + auch direkt mit Hexadezimalzahlen im Kopf. + + \end{itemize} + + \exercise{Ausgabe von Hexadezimalzahlen} + + Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)}, + die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x} + als Hexadezimalzahl ausgibt. + (Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.) + + Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit + der Formatspezifikation \lstinline{%x} als fertige Lösung, + sondern programmieren Sie die nötige Ausgabe selbst. + (Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.) + + Die Verwendung von \lstinline{printf()} + mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d} + oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig. + + \points{8} + + (Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht, + aber nicht zwingend.) + + \solution + + Um die Ziffern von \lstinline{x} zur Basis 16 zu isolieren, + berechnen wir \lstinline{x % 16} (modulo 16 = Rest bei Division durch 16) + und dividieren anschließend \lstinline{x} durch 16, + solange bis \lstinline{x} den Wert 0 erreicht. + + Wenn wir die auf diese Weise ermittelten Ziffern direkt ausgeben, + sind sie \emph{Little-Endian}, erscheinen also in umgekehrter Reihenfolge. + Die Datei \gitfile{hp}{2023ws/20231102}{loesung-2-1.c} setzt diesen Zwischenschritt um. + + Die Ausgabe der Ziffern erfolgt in \gitfile{hp}{2023ws/20231102}{loesung-2-1.c} + über \lstinline{printf ("%d")} + für die Ziffern 0 bis 9. Für die darüberliegenden Ziffern + wird der Buchstabe \lstinline{a} um die Ziffer abzüglich 10 inkrementiert + und der erhaltene Wert mit \lstinline{printf ("%c")} als Zeichen ausgegeben. + + Um die umgekehrte Reihenfolge zu beheben, + speichern wir die Ziffern von \lstinline{x} + in einem Array \lstinline{digits[]} zwischen + und geben sie anschließend in einer zweiten Schleife + in umgekehrter Reihenfolge aus (siehe \gitfile{hp}{2023ws/20231102}{loesung-2-2.c}). + Da wir wissen, daß \lstinline{x} eine 32-Bit-Zahl ist + und daher höchstens 8 Hexadezimalziffern haben kann, + ist 8 eine sinnvolle Länge für das Ziffern-Array \lstinline{digits[8]}. + + Nun sind die Ziffern in der richtigen Reihenfolge, + aber wir erhalten zusätzlich zu den eigentlichen Ziffern führende Nullen. + Da in der Aufgabenstellung nicht von führenden Nullen die Rede war, + sind diese nicht verboten; \gitfile{hp}{2023ws/20231102}{loesung-2-2.c} ist daher + eine richtige Lösung der Aufgabe. + + \breath + + Wenn wir die führenden Nullen vermeiden wollen, + können wir die \lstinline{for}-Schleifen durch \lstinline{while}-Schleifen ersetzen. + Die erste Schleife zählt hoch, solange \lstinline{x} ungleich 0 ist; + die zweite zählt von dem erreichten Wert aus wieder herunter + -- siehe \gitfile{hp}{2023ws/20231102}{loesung-2-3.c}. + Da wir wissen, daß die Zahl \lstinline{x} höchstens 32 Bit, + also höchstens 8 Hexadezimalziffern hat, + wissen wir, daß \lstinline{i} höchstens den Wert 8 erreichen kann, + das Array also nicht überlaufen wird. + + Man beachte, daß der Array-Index nach der ersten Schleife "`um einen zu hoch"' ist. + In der zweiten Schleife muß daher \emph{zuerst\/} der Index dekrementiert werden. + Erst danach darf ein Zugriff auf \lstinline{digit[i]} erfolgen. + + \breath + + Alternativ können wir auch mitschreiben, + ob bereits eine Ziffer ungleich Null ausgegeben wurde, + und andernfalls die Ausgabe von Null-Ziffern unterdrücken + -- siehe \gitfile{hp}{2023ws/20231102}{loesung-2-4.c}. + + \breath + + Weitere Möglichkeiten ergeben sich, wenn man bedenkt, + daß eine Hexadezimalziffer genau einer Gruppe von vier Binärziffern entspricht. + Eine Bitverschiebung um 4 nach rechts + ist daher dasselbe wie eine Division durch 16, + und eine Und-Verknüpfung mit 15$_{10}$ = f$_{16}$ = 1111$_2$ + ist dasselbe wie die Operation Modulo 16. + Die Datei \gitfile{hp}{2023ws/20231102}{loesung-2-5.c} ist eine in dieser Weise abgewandelte Variante + von \gitfile{hp}{2023ws/20231102}{loesung-2-3.c}. + + Mit dieser Methode kann man nicht nur auf die jeweils unterste Ziffer, + sondern auf alle Ziffern direkt zugreifen. + Damit ist kein Array als zusätzlicher Speicher mehr nötig. + Die Datei \gitfile{hp}{2023ws/20231102}{loesung-2-6.c} setzt dies auf einfache Weise um. + Sie gibt wieder führende Nullen mit aus, + ist aber trotzdem eine weitere richtige Lösung der Aufgabe. + + Die führenden Nullen ließen sich auf die gleiche Weise vermeiden + wie in \gitfile{hp}{2023ws/20231102}{loesung-2-4.c}. + + Die Bitverschiebungsmethode hat den Vorteil, + daß kein zusätzliches Array benötigt wird. + Auch wird die als Parameter übergebene Zahl \lstinline{x} nicht verändert, + was bei größeren Zahlen, die über Zeiger übergeben werden, von Vorteil sein kann. + Demgegenüber steht der Nachteil, + daß diese Methode nur für eine ganze Anzahl von Bits funktioniert, + also für Basen, die Zweierpotenzen sind (z.\,B.\ 2, 8, 16, 256). + Für alle anderen Basen (z.\,B.\ 10) eignet sich nur die Methode + mit Division und Modulo-Operation. + + \exercise{Einfügen in Strings} + + Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231102}{aufgabe-3.c}): +% \begin{lstlisting}[style=numbered] + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + void insert_into_string (char src, char *target, int pos) + { + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; + } + + int main (void) + { + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; + } + \end{lstlisting} + Die Ausgabe des Programms lautet: + \lstinline[style=terminal]{Hochschhhhhhhhhhh} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie, wie die Ausgabe zustandekommt. + \points{3} +% \workspace{12} + \item + Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.\par + Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten. + \points{2} +% \workspace{13} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} +% \item +% Schreiben Sie eine Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)}, +% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist +% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle +% einfügt. Diese Funktion darf die bereits vorhandene Funktion +% \lstinline|insert_into_string()| aufrufen.\\ +% \points{4}\par +% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm: +% \begin{lstlisting}[gobble=8] +% char test[100] = ""; +% insert_into_string_sorted ('c', test); +% insert_into_string_sorted ('a', test); +% insert_into_string_sorted ('d', test); +% insert_into_string_sorted ('b', test); +% \end{lstlisting} +% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten. +% \workspace{14} +% \item +% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings) +% arbeitet Ihre Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% und warum? +% \points{1} +% \workspace{10} +% \item +% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\ +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% so gestalten kann,\\ +% daß sie in $\mathcal{O}(\log n)$ arbeitet. +% \points{3} +% \workspace{35} + \end{enumerate} + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Erklären Sie, wie die Ausgabe zustandekommt.} + + In der Schleife wird \emph{zuerst\/} der nächste Buchstabe \lstinline{target[i + 1]} + gleich dem aktuellen gesetzt + und \emph{danach\/} der Zähler \lstinline{i} erhöht. + Dadurch wird im nächsten Schleifendurchlauf der bereits verschobene Buchstabe + noch weiter geschoben und letztlich alle Buchstaben in \lstinline{target[]} + durch den an der Stelle \lstinline{pos} ersetzt. + + \item + \textbf{Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.}\par + \textbf{Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten.} + + Um im String "`Platz zu schaffen"', muß man von hinten beginnen, + also die Schleife umdrehen\\ + (siehe: \gitfile{hp}{2023ws/20231102}{loesung-3.c}): + \begin{lstlisting}{gobble=8} + for (int i = len; i >= pos; i--) + target[i + 1] = target[i]; + \end{lstlisting} + + \item + \textbf{Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} + ersetzen und warum?} + + Die Schreibweise \lstinline{test[]} bedeutet, + daß der Compiler selbst zählt, wieviel Speicherplatz der String benötigt, + un dann genau die richtige Menge Speicher reserviert + (anstatt, wie wir es manuell getan haben, pauschal Platz für 100 Zeichen). + + Wenn wir nun in den String ein zusätzliches Zeichen einfügen, + ist dafür kein Speicherplatz reserviert worden, + und wir \textbf{überschreiben} dann Speicher, an dem sich andere Variable befinden, + was zu einem \textbf{Absturz} führen kann. + + Da wir hier nur ein einziges Zeichen schreiben, + wird dieser Fehler nicht sofort auffallen. + Dies ist schlimmer, als wenn das Programm direkt beim ersten Test abstürzt, + denn dadurch entsteht bei uns der Eindruck, es sei in Ordnung. + Wenn danach der Fehler in einer Produktivumgebung auftritt, + kann dadurch Schaden entstehen -- je nach Einsatzgebiet der Software + u.\,U.\ erheblicher Vermögens-, Sach- und/oder Personenschaden + (z.\,B.\ Absturz eines Raumflugkörpers). + + \item + \textbf{Was kann passieren, wenn Sie + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} + ersetzen und warum?} + + In diesem Fall wird der Speicher für den eigentlichen String + in einem unbenannten, \textbf{nicht schreibbaren} Teil des Speichers reserviert. + Unser Versuch, dorthin ein zusätzliches Zeichen zu schreiben, + fürt dann normalerweise zu einem \textbf{Absturz}. + + In manchen Systemen (Betriebssystem, Compiler, \dots) + ist der Speicherbereich tatsächlich sehr wohl schreibbar. + In diesem Fall tritt der Absturz nicht immer und nicht immer sofort auf -- + genau wie in Aufgabenteil (c). + + \end{enumerate} + +\end{document} diff --git a/20231102/hp-uebung-20231102.pdf b/20231102/hp-uebung-20231102.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4448879c71b160a6acd1b949647b573112303358 Binary files /dev/null and b/20231102/hp-uebung-20231102.pdf differ diff --git a/20231102/hp-uebung-20231102.tex b/20231102/hp-uebung-20231102.tex new file mode 100644 index 0000000000000000000000000000000000000000..803fb4a2ed25eb774af13333daa50f7ce56e8afb --- /dev/null +++ b/20231102/hp-uebung-20231102.tex @@ -0,0 +1,227 @@ +% hp-uebung-20231102.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: Zahlensysteme, Ausgabe von Hexadezimalzahlen, Einfügen in Strings + +\documentclass[a4paper]{article} + +\usepackage{pgscript} + +\begin{document} + + \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 2.\ November 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{Zahlensysteme} + + Wandeln Sie ohne Hilfsmittel + + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Dezimal: + \begin{itemize} + \item[(a)] + 0010\,0000$_2$ + \item[(b)] + 42$_{16}$ + \item[(c)] + 17$_8$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Hexadezimal: + \begin{itemize} + \item[(d)] + 0010\,0000$_2$ + \item[(e)] + 42$_{10}$ + \item[(f)] + 192.168.20.254$_{256}$ + \end{itemize} + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{itemize} + \item + nach Binär: + \begin{itemize} + \item[(g)] + 750$_8$ + \item[(h)] + 42$_{10}$ + \item[(i)] + AFFE$_{16}$ + \end{itemize} + \end{itemize} + \end{minipage} + + \medskip + + Berechnen Sie ohne Hilfsmittel: + \begin{itemize} + \item[(j)] + 750$_8$ \& 666$_8$ + \item[(k)] + A380$_{16}$ + B747$_{16}$ + \item[(l)] + AFFE$_{16} >> 1$ + \end{itemize} + + Die tiefgestellte Zahl steht für die Basis des Zahlensystems. + Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12} + + (In der Klausur sind Hilfsmittel zugelassen, + daher ist dies \emph{keine\/} typische Klausuraufgabe.) + + \exercise{Ausgabe von Hexadezimalzahlen} + + Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)}, + die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x} + als Hexadezimalzahl ausgibt. + (Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.) + + Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit + der Formatspezifikation \lstinline{%x} als fertige Lösung, + sondern programmieren Sie die nötige Ausgabe selbst. + (Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.) + + Die Verwendung von \lstinline{printf()} + mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d} + oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig. + + \points{8} + + (Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht, + aber nicht zwingend.) + + \clearpage + + \exercise{Einfügen in Strings} + + Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231102}{aufgabe-3.c}): +% \begin{lstlisting}[style=numbered] + \begin{lstlisting} + #include <stdio.h> + #include <string.h> + + void insert_into_string (char src, char *target, int pos) + { + int len = strlen (target); + for (int i = pos; i < len; i++) + target[i+1] = target[i]; + target[pos] = src; + } + + int main (void) + { + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; + } + \end{lstlisting} + Die Ausgabe des Programms lautet: + \lstinline[style=terminal]{Hochschhhhhhhhhhh} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie, wie die Ausgabe zustandekommt. + \points{3} +% \workspace{12} + \item + Schreiben Sie die Funktion \lstinline|insert_into_string()| so um, + daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos} + in den String \lstinline{target} einfügt.\par + Die Ausgabe des Programms müßte dann + \lstinline[style=terminal]{Hochschule Bochum} lauten. + \points{2} +% \workspace{13} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char test[] = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} + \item + Was kann passieren, wenn Sie die Zeile + \lstinline{char test[100] = "Hochshule Bochum";}\\ + durch + \lstinline{char *test = "Hochshule Bochum";} ersetzen? + Begründen Sie Ihre Antwort. + \points{2} +% \workspace{10} +% \item +% Schreiben Sie eine Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)}, +% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist +% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle +% einfügt. Diese Funktion darf die bereits vorhandene Funktion +% \lstinline|insert_into_string()| aufrufen.\\ +% \points{4}\par +% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm: +% \begin{lstlisting}[gobble=8] +% char test[100] = ""; +% insert_into_string_sorted ('c', test); +% insert_into_string_sorted ('a', test); +% insert_into_string_sorted ('d', test); +% insert_into_string_sorted ('b', test); +% \end{lstlisting} +% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten. +% \workspace{14} +% \item +% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings) +% arbeitet Ihre Funktion +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% und warum? +% \points{1} +% \workspace{10} +% \item +% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\ +% \lstinline{void insert_into_string_sorted (char src, char *target)} +% so gestalten kann,\\ +% daß sie in $\mathcal{O}(\log n)$ arbeitet. +% \points{3} +% \workspace{35} + \end{enumerate} + + \begin{flushright} + \textit{Viel Erfolg!} + \end{flushright} + + \makeatletter + \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} + \makeatother + +\end{document} diff --git a/20231102/loesung-2-1.c b/20231102/loesung-2-1.c new file mode 100644 index 0000000000000000000000000000000000000000..98b2f03f19d21aa2a794fef1f3f98feff95f5142 --- /dev/null +++ b/20231102/loesung-2-1.c @@ -0,0 +1,22 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + while (x) + { + int digit = x % 16; + if (digit < 10) + printf ("%d", digit); + else + printf ("%c", 'a' + digit - 10); + x /= 16; + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-2-2.c b/20231102/loesung-2-2.c new file mode 100644 index 0000000000000000000000000000000000000000..35aa3b3aea6fc8faaa55c7d5382f0a8de9282aee --- /dev/null +++ b/20231102/loesung-2-2.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + for (int i = 0; i < 8; i++) + { + digit[i] = x % 16; + x /= 16; + } + for (int i = 7; i >= 0; i--) + { + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-2-3.c b/20231102/loesung-2-3.c new file mode 100644 index 0000000000000000000000000000000000000000..2462f2b537896722d8d1774a5d47f374ee5ef7fa --- /dev/null +++ b/20231102/loesung-2-3.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + int i = 0; + while (x) + { + digit[i] = x % 16; + x /= 16; + i++; + } + while (i > 0) + { + i--; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-2-4.c b/20231102/loesung-2-4.c new file mode 100644 index 0000000000000000000000000000000000000000..5083dcb865c86beafd43ce3e8837510b13cbe850 --- /dev/null +++ b/20231102/loesung-2-4.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + for (int i = 0; i < 8; i++) + { + digit[i] = x % 16; + x /= 16; + } + int printing = 0; + for (int i = 7; i >= 0; i--) + { + if (printing || digit[i] != 0) + { + printing = 1; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-2-5.c b/20231102/loesung-2-5.c new file mode 100644 index 0000000000000000000000000000000000000000..e3446edb4a40348ac14da420f344c208f8916f7e --- /dev/null +++ b/20231102/loesung-2-5.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + char digit[8]; + int i = 0; + while (x) + { + digit[i] = x & 0x0000000f; + x >>= 4; + i++; + } + while (i > 0) + { + i--; + if (digit[i] < 10) + printf ("%d", digit[i]); + else + printf ("%c", 'a' + digit[i] - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-2-6.c b/20231102/loesung-2-6.c new file mode 100644 index 0000000000000000000000000000000000000000..7b8e8e1a9d7285b8a1e02ff1a91310f1dc02ed5b --- /dev/null +++ b/20231102/loesung-2-6.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <stdint.h> + +void print_hex (uint32_t x) +{ + int i = 32; + while (i > 0) + { + i -= 4; + int digit = (x >> i) & 0x0000000f; + if (digit < 10) + printf ("%d", digit); + else + printf ("%c", 'a' + digit - 10); + } +} + +int main (void) +{ + print_hex (0xcafe42); + printf ("\n"); + return 0; +} diff --git a/20231102/loesung-3.c b/20231102/loesung-3.c new file mode 100644 index 0000000000000000000000000000000000000000..85abfcf3e1e4bacf454acd10f6832b757a64ac35 --- /dev/null +++ b/20231102/loesung-3.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <string.h> + +void insert_into_string (char src, char *target, int pos) +{ + int len = strlen (target); + for (int i = len; i >= pos; i--) + target[i + 1] = target[i]; + target[pos] = src; +} + +int main (void) +{ + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; +} diff --git a/20231102/logo-hochschule-bochum-cvh-text-v2.pdf b/20231102/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20231102/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/20231102/logo-hochschule-bochum.pdf b/20231102/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20231102/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20231102/pgscript.sty b/20231102/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20231102/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20231102/pgslides.sty b/20231102/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20231102/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file