Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 2016ws
  • 2017ws
  • 2018ws
  • 2019ws
  • 2020ws
  • 2021ws
  • 2022ws
  • 2023ws
  • 2024ws
9 results

Target

Select target project
No results found
Select Git revision
  • 2016ws
  • 2017ws
  • 2018ws
  • master
4 results
Show changes

Commits on Source 265

165 additional commits have been omitted to prevent performance issues.
1000 files
+ 29930
7742
Compare changes
  • Side-by-side
  • Inline

Files

20191010/hello-gtk.c

deleted100644 → 0
+0 −23
Original line number Original line Diff line number Diff line
#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;
}

20191010/hello.pas

deleted100644 → 0
+0 −5
Original line number Original line Diff line number Diff line
program Hello;

begin
  WriteLn ('Hello, world!')
end.

20191010/hp-20191010-fig1.tex

deleted100644 → 0
+0 −60
Original line number Original line Diff line number Diff line
\documentclass{article}
\input tmp.inputs
\pagestyle{empty}
\begin{document}
      \psscalebox{0.8}{%
        \begin{pspicture}(-5,0)(12,12)
          \small
          \psset{unit=0.5cm}
          \psline[arrows=<->](-1,0)(-1,22)
          \rput(-1.3,0){\makebox(0,0)[br]{\textbf{gegenständlich}}}
          \rput(-1.3,22){\makebox(0,0)[tr]{\textbf{abstrakt}}}
          \rput(-1.3,2){\makebox(0,0)[r]{Elektromagnetismus, Halbleiter}}
          \rput(-1.3,4){\makebox(0,0)[r]{Elektronische Bauelemente}}
          \rput(-1.3,6){\makebox(0,0)[r]{Logik-Schaltkreise}}
          \rput(-1.3,8){\makebox(0,0)[r]{Prozessoren}}
          \rput(-1.3,9){\makebox(0,0)[r]{Maschinensprache}}
          \rput(-1.3,10){\makebox(0,0)[r]{Assembler}}
          \rput(-1.3,11){\makebox(0,0)[r]{Ein-/Ausgabe}}
          \rput(-1.3,12.35){\makebox(0,0)[r]{\textbf{hardwarenahe Programmierung} (z.\,B.\ in C)}}
          \rput(-1.3,14){\makebox(0,0)[r]{\shortstack[r]{abstrahierende Programmierung\\(z.\,B.\ in C++, Java)}}}
%          \rput(-1.3,15){\makebox(0,0)[r]{Programmierung}}
          \rput(-1.3,16){\makebox(0,0)[r]{Algorithmen, Datenstrukturen, Software-Entwurf}}
          \rput(-1.3,17){\makebox(0,0)[r]{Requirements Engineering}}
          \rput(-1.3,18){\makebox(0,0)[r]{formale Sprachen, Berechenbarkeit}}
          \rput(-1.3,19){\makebox(0,0)[r]{mathematische Strukturen}}
          \rput(-1.3,20){\makebox(0,0)[r]{mathematische Beweise}}
          \rput(2.1,0.5){\makebox(0,0)[l]{Physik}}
          \rput(4.1,4){\makebox(0,0)[l]{Elektrotechnik}}
          \rput(6.1,8){\makebox(0,0)[l]{Rechnertechnik}}
          \rput(8.1,12.35){\makebox(0,0)[l]{angewandte Informatik}}
          \rput(10.1,16){\makebox(0,0)[l]{\shortstack[l]{Softwaretechnik und\\theoretische Informatik}}}
          \rput(12.1,21){\makebox(0,0)[l]{Mathematik}}
          \psset{linewidth=0.001,linestyle=none,fillstyle=gradient,gradmidpoint=1.0,gradlines=1000}
          \definecolor{RGBwhite}{rgb}{1.0,1.0,1.0}
          \definecolor{RGBblue}{rgb}{0.0,0.0,1.0}
          \definecolor{RGBred}{rgb}{1.0,0.0,0.0}
          \definecolor{RGBgreen}{rgb}{0.0,1.0,0.0}
          \definecolor{RGByellow}{rgb}{1.0,1.0,0.0}
          \definecolor{RGBorange}{rgb}{1.0,0.7,0.0}
          \definecolor{RGBgrey}{rgb}{0.7,0.7,0.7}
          \rput(0,2){\psframe[gradbegin=RGBwhite,gradend=RGBblue](2,2)}
          \rput(0,0){\psframe[fillstyle=solid,fillcolor=RGBblue](2,2.01)}
          \rput(2,6){\psframe[gradbegin=RGBwhite,gradend=RGBred](2,2)}
          \rput(2,2){\psframe[gradbegin=RGBred,gradend=RGBwhite](2,2)}
          \rput(2,3.99){\psframe[fillstyle=solid,fillcolor=RGBred](2,2.02)}
          \rput(4,10){\psframe[gradbegin=RGBwhite,gradend=RGBgreen](2,2)}
          \rput(4,6){\psframe[gradbegin=RGBgreen,gradend=RGBwhite](2,2)}
          \rput(4,7.99){\psframe[fillstyle=solid,fillcolor=RGBgreen](2,2.02)}
          \rput(6,14){\psframe[gradbegin=RGBwhite,gradend=RGByellow](2,2)}
          \rput(6,10){\psframe[gradbegin=RGByellow,gradend=RGBwhite](2,2)}
          \rput(6,11.99){\psframe[fillstyle=solid,fillcolor=RGByellow](2,2.02)}
          \rput(8,18){\psframe[gradbegin=RGBwhite,gradend=RGBorange](2,2)}
          \rput(8,14){\psframe[gradbegin=RGBorange,gradend=RGBwhite](2,2)}
          \rput(8,15.99){\psframe[fillstyle=solid,fillcolor=RGBorange](2,2.02)}
          \rput(10,18){\psframe[gradbegin=RGBgrey,gradend=RGBwhite](2,2)}
          \rput(10,19.99){\psframe[fillstyle=solid,fillcolor=RGBgrey](2,2.01)}
        \end{pspicture}
      }
    
\end{document}

20191017/functions-5.c

deleted100644 → 0
+0 −26
Original line number Original line Diff line number Diff line
#include <stdio.h>

int a = 0, b = 3;

void foo (void)
{
  b++;
  static int a = 5;
  int b = 7;
  printf ("foo(): a = %d, b = %d\n", a, b);
  a++;
}

int main (void)
{
  printf ("main(): a = %d, b = %d\n", a, b);
  foo ();
  printf ("main(): a = %d, b = %d\n", a, b);
  a = b = 12;
  printf ("main(): a = %d, b = %d\n", a, b);
/*
  foo ();
  printf ("main(): a = %d, b = %d\n", a, b);
*/
  return 0;
}

20191017/functions-6.c

deleted100644 → 0
+0 −26
Original line number Original line Diff line number Diff line
#include <stdio.h>

int a = 0, b = 3;

void foo (void)
{
  b++;
  static int a = 5;
  int b = 7;
  printf ("foo(): a = %d, b = %d\n", a, b);
  a++;
}

int main (void)
{
  printf ("main(): a = %d, b = %d\n", a, b);
  foo ();
  printf ("main(): a = %d, b = %d\n", a, b);
  a, b = 12;
  printf ("main(): a = %d, b = %d\n", a, b);
/*
  foo ();
  printf ("main(): a = %d, b = %d\n", a, b);
*/
  return 0;
}

20191017/functions-7.c

deleted100644 → 0
+0 −26
Original line number Original line Diff line number Diff line
#include <stdio.h>

int a = 0, b = 3;

void foo (void)
{
  b++;
  static int a = 5;
  int b = 7;
  printf ("foo(): a = %d, b = %d\n", a, b);
  a++;
}

int main (void)
{
  printf ("main(): a = %d, b = %d\n", a, b);
  foo ();
  printf ("main(): a = %d, b = %d\n", a, b);
  a = b = 12;
  printf ("main(): a = %d, b = %d\n", a, b);
  foo ();
/*
  printf ("main(): a = %d, b = %d\n", a, b);
*/
  return 0;
}

20191017/functions-8.s

deleted100644 → 0
+0 −88
Original line number Original line Diff line number Diff line
	.file	"functions-8.c"
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"foo(): a = %d, b = %d\n"
	.text
	.globl	foo
	.type	foo, @function
foo:
.LFB11:
	.cfi_startproc
	subq	$8, %rsp
	.cfi_def_cfa_offset 16
	addl	$1, b(%rip)
	movl	$7, %edx
	movl	a.2249(%rip), %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	addl	$1, a.2249(%rip)
	addq	$8, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE11:
	.size	foo, .-foo
	.section	.rodata.str1.1
.LC1:
	.string	"main(): a = %d, b = %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB12:
	.cfi_startproc
	subq	$8, %rsp
	.cfi_def_cfa_offset 16
	movl	b(%rip), %edx
	movl	a(%rip), %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	call	foo
	movl	b(%rip), %edx
	movl	a(%rip), %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$12, b(%rip)
	movl	$12, a(%rip)
	movl	$12, %edx
	movl	$12, %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	call	foo
	movl	b(%rip), %edx
	movl	a(%rip), %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	addq	$8, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE12:
	.size	main, .-main
	.data
	.align 4
	.type	a.2249, @object
	.size	a.2249, 4
a.2249:
	.long	5
	.globl	b
	.align 4
	.type	b, @object
	.size	b, 4
b:
	.long	3
	.globl	a
	.bss
	.align 4
	.type	a, @object
	.size	a, 4
a:
	.zero	4
	.ident	"GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
	.section	.note.GNU-stack,"",@progbits

20191017/hello-1.s

deleted100644 → 0
+0 −26
Original line number Original line Diff line number Diff line
	.file	"hello-1.c"
	.section	.rodata
.LC0:
	.string	"Hello, world!"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	leaq	.LC0(%rip), %rdi
	call	puts@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
	.section	.note.GNU-stack,"",@progbits

20191017/hello-2.s

deleted100644 → 0
+0 −21
Original line number Original line Diff line number Diff line
	.file	"hello-2.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
	.section	.note.GNU-stack,"",@progbits

20191017/hp-20191017-fig1.tex

deleted100644 → 0
+0 −60
Original line number Original line Diff line number Diff line
\documentclass{article}
\input tmp.inputs
\pagestyle{empty}
\begin{document}
      \psscalebox{0.8}{%
        \begin{pspicture}(-5,0)(12,12)
          \small
          \psset{unit=0.5cm}
          \psline[arrows=<->](-1,0)(-1,22)
          \rput(-1.3,0){\makebox(0,0)[br]{\textbf{gegenständlich}}}
          \rput(-1.3,22){\makebox(0,0)[tr]{\textbf{abstrakt}}}
          \rput(-1.3,2){\makebox(0,0)[r]{Elektromagnetismus, Halbleiter}}
          \rput(-1.3,4){\makebox(0,0)[r]{Elektronische Bauelemente}}
          \rput(-1.3,6){\makebox(0,0)[r]{Logik-Schaltkreise}}
          \rput(-1.3,8){\makebox(0,0)[r]{Prozessoren}}
          \rput(-1.3,9){\makebox(0,0)[r]{Maschinensprache}}
          \rput(-1.3,10){\makebox(0,0)[r]{Assembler}}
          \rput(-1.3,11){\makebox(0,0)[r]{Ein-/Ausgabe}}
          \rput(-1.3,12.35){\makebox(0,0)[r]{\textbf{hardwarenahe Programmierung} (z.\,B.\ in C)}}
          \rput(-1.3,14){\makebox(0,0)[r]{\shortstack[r]{abstrahierende Programmierung\\(z.\,B.\ in C++, Java)}}}
%          \rput(-1.3,15){\makebox(0,0)[r]{Programmierung}}
          \rput(-1.3,16){\makebox(0,0)[r]{Algorithmen, Datenstrukturen, Software-Entwurf}}
          \rput(-1.3,17){\makebox(0,0)[r]{Requirements Engineering}}
          \rput(-1.3,18){\makebox(0,0)[r]{formale Sprachen, Berechenbarkeit}}
          \rput(-1.3,19){\makebox(0,0)[r]{mathematische Strukturen}}
          \rput(-1.3,20){\makebox(0,0)[r]{mathematische Beweise}}
          \rput(2.1,0.5){\makebox(0,0)[l]{Physik}}
          \rput(4.1,4){\makebox(0,0)[l]{Elektrotechnik}}
          \rput(6.1,8){\makebox(0,0)[l]{Rechnertechnik}}
          \rput(8.1,12.35){\makebox(0,0)[l]{angewandte Informatik}}
          \rput(10.1,16){\makebox(0,0)[l]{\shortstack[l]{Softwaretechnik und\\theoretische Informatik}}}
          \rput(12.1,21){\makebox(0,0)[l]{Mathematik}}
          \psset{linewidth=0.001,linestyle=none,fillstyle=gradient,gradmidpoint=1.0,gradlines=1000}
          \definecolor{RGBwhite}{rgb}{1.0,1.0,1.0}
          \definecolor{RGBblue}{rgb}{0.0,0.0,1.0}
          \definecolor{RGBred}{rgb}{1.0,0.0,0.0}
          \definecolor{RGBgreen}{rgb}{0.0,1.0,0.0}
          \definecolor{RGByellow}{rgb}{1.0,1.0,0.0}
          \definecolor{RGBorange}{rgb}{1.0,0.7,0.0}
          \definecolor{RGBgrey}{rgb}{0.7,0.7,0.7}
          \rput(0,2){\psframe[gradbegin=RGBwhite,gradend=RGBblue](2,2)}
          \rput(0,0){\psframe[fillstyle=solid,fillcolor=RGBblue](2,2.01)}
          \rput(2,6){\psframe[gradbegin=RGBwhite,gradend=RGBred](2,2)}
          \rput(2,2){\psframe[gradbegin=RGBred,gradend=RGBwhite](2,2)}
          \rput(2,3.99){\psframe[fillstyle=solid,fillcolor=RGBred](2,2.02)}
          \rput(4,10){\psframe[gradbegin=RGBwhite,gradend=RGBgreen](2,2)}
          \rput(4,6){\psframe[gradbegin=RGBgreen,gradend=RGBwhite](2,2)}
          \rput(4,7.99){\psframe[fillstyle=solid,fillcolor=RGBgreen](2,2.02)}
          \rput(6,14){\psframe[gradbegin=RGBwhite,gradend=RGByellow](2,2)}
          \rput(6,10){\psframe[gradbegin=RGByellow,gradend=RGBwhite](2,2)}
          \rput(6,11.99){\psframe[fillstyle=solid,fillcolor=RGByellow](2,2.02)}
          \rput(8,18){\psframe[gradbegin=RGBwhite,gradend=RGBorange](2,2)}
          \rput(8,14){\psframe[gradbegin=RGBorange,gradend=RGBwhite](2,2)}
          \rput(8,15.99){\psframe[fillstyle=solid,fillcolor=RGBorange](2,2.02)}
          \rput(10,18){\psframe[gradbegin=RGBgrey,gradend=RGBwhite](2,2)}
          \rput(10,19.99){\psframe[fillstyle=solid,fillcolor=RGBgrey](2,2.01)}
        \end{pspicture}
      }
    
\end{document}

20191017/if-10.c

deleted100644 → 0
+0 −12
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  int a = 7;
  int b;
  if ((b += a) == 0)
    printf ("Bitte nicht durch 0 teilen!\n");
  else
    printf ("100 / a = %d\n", 100 / a);
  return 0;
}

20191017/if-11.c

deleted100644 → 0
+0 −12
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  int a = 7;
  int b = 0;
  if ((b += a) == 0)
    printf ("Bitte nicht durch 0 teilen!\n");
  else
    printf ("100 / a = %d\n", 100 / a);
  return 0;
}

20191017/if-3.c

deleted100644 → 0
+0 −10
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  int b = 12;
  if (b)
    printf ("100 / b = %d\n", 100 / b);
    printf ("100 % b = %d\n", 100 % b);
  return 0;
}

20191017/if-8.c

deleted100644 → 0
+0 −11
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  int a = 7;
  if (a = 0)
    printf ("Bitte nicht durch 0 teilen!\n");
  else
    printf ("100 / a = %d\n", 100 / a);
  return 0;
}

20191017/if-9.c

deleted100644 → 0
+0 −12
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  int a = 7;
  int b;
  if ((b = a) == 0)
    printf ("Bitte nicht durch 0 teilen!\n");
  else
    printf ("100 / a = %d\n", 100 / a);
  return 0;
}

20191017/while-1.c

deleted100644 → 0
+0 −3
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void) { while (0) printf ("Hello, world!\n"); return 0; }

20191017/while-5.c

deleted100644 → 0
+0 −8
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void) {
    while (1) {
        printf ("Hello, world!\n");
    }
  return 0;
}

20191017/while-6.c

deleted100644 → 0
+0 −11
Original line number Original line Diff line number Diff line
#include <stdio.h>

int
main (void)
{
  while (1)
    {
      printf ("Hello, world!\n");
    }
  return 0;
}

20191024/aufgabe-2.c

deleted100644 → 0
+0 −18
Original line number Original line Diff line number Diff line
  year = ORIGINYEAR;  /* = 1980 */

  while (days > 365)
    {
      if (IsLeapYear (year))
        {
          if (days > 366)
            {
              days -= 366;
              year += 1;
            }
        }
      else
        {
          days -= 365;
          year += 1;
        }
    }

20191024/test-5.c

deleted100644 → 0
+0 −7
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  printf ("Die Antwort lautet: %x.\n", 'B');
  return 0;
}

20191031/chars-1.c

deleted100644 → 0
+0 −7
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  printf ("%c\n", 117);
  return 0;
}

20191031/files-2.c

deleted100644 → 0
+0 −9
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  FILE *f = fopen ("bla/fhello.txt", "w");
  fprintf (f, "Hello, world!\n");
  fclose (f);
  return 0;
}

20191031/files-3.c

deleted100644 → 0
+0 −9
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  FILE *f = fopen ("c:\\windows\\system\\kern64.dll", "w");
  fprintf (f, "Hello, world!\n");
  fclose (f);
  return 0;
}
+0 −414
Original line number Original line Diff line number Diff line
% hp-musterloesung-20191024.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019  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: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm

\documentclass[a4paper]{article}

\usepackage{pgscript}

\begin{document}

  \section*{Hardwarenahe Programmierung\\
            Musterlösung zu den Übungsaufgaben -- 31.\ Oktober 2019}

  \exercise{Strings}

  Strings werden in der Programmiersprache C
  durch Zeiger auf \lstinline{char}-Variable realisiert.

  Wir betrachten die folgende Funktion (Datei: \gitfile{hp}{20191031}{aufgabe-1.c}):
  \begin{center}
    \begin{minipage}{8cm}
      \begin{lstlisting}[gobble=8]
        int fun_1 (char *s1, char *s2)
        {
          int result = 1;
          for (int i = 0; s1[i] && s2[i]; i++)
            if (s1[i] != s2[i])
              result = 0;
          return result;
        }
      \end{lstlisting}
    \end{minipage}%
  \end{center}
  \begin{itemize}
    \item[(a)]
      Was bewirkt die Funktion? % \points{3}
    \item[(b)]
      Welchen Sinn hat die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife? % \points{2}
    \item[(c)]
      Was würde sich ändern, wenn die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife\\
      zu "`\lstinline{s1[i]}"' verkürzt würde? % \points{3}
%    \item[(d)]
%      Von welcher Ordnung (Landau-Symbol) ist die Funktion \lstinline{fun_1()}
%      hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen in den Strings
%      -- und warum? % \points{2}
    \item[(d)]
      Schreiben Sie eine eigene Funktion,
      die dieselbe Aufgabe erledigt wie \lstinline{fun_1()}, nur effizienter.
%      und geben Sie die Ordnung (Landau-Symbol) der von Ihnen geschriebenen Funktion an. % \points{5}
  \end{itemize}

  \solution

  \begin{itemize}
    \item[(a)]
      \textbf{Was bewirkt die Funktion?}

      Sie vergleicht zwei Strings miteinander bis zur Länge des kürzeren Strings
      und gibt bei Gleichheit 1 zurück, ansonsten 0.

      Mit anderen Worten:
      Die Funktion prüft, ob zwei Strings bis zur Länge des kürzeren übereinstimmen,
      und gibt bei Gleichheit 1 zurück, ansonsten 0.

      Die Funktion prüft insbesondere \textbf{nicht} zwei Strings auf Gleichheit,
      und sie ist \textbf{nicht} funktionsgleich zur
      Standard-Bibliotheksfunktion \lstinline{strcmp()}.

    \item[(b)]
      \textbf{Welchen Sinn hat die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife?}

      Die Bedingung prüft, ob \emph{bei einem der beiden Strings\/}
      die Ende-Markierung (Null-Symbol) erreicht ist.
      Falls ja, wird die Schleife beendet.

    \item[(c)]
      \textbf{Was würde sich ändern, wenn die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife\\
      zu "`\lstinline{s1[i]}"' verkürzt würde?}

      In diesem Fall würde nur für \lstinline{s1} geprüft,
      ob das Ende erreicht ist.
      Wenn \lstinline{s1} länger ist als \lstinline{s2},
      würde \lstinline{s2} über sein Ende hinaus ausgelesen.
      Dies kann zu Lesezugriffen auf Speicher außerhalb des Programms
      und damit zu einem Absturz führen
      ("`Speicherzugriffsfehler"', "`Schutzverletzung"').

    \item[(d)]
      \textbf{Schreiben Sie eine eigene Funktion,
      die dieselbe Aufgabe erledigt wie \lstinline{fun_1()}, nur effizienter.}

      Die Effizienz läßt sich steigern, indem man die Schleife abbricht,
      sobald das Ergebnis feststeht.
      Es folgen drei Möglichkeiten, dies zu realisieren.
  \end{itemize}

  \begin{center}
    \begin{minipage}[t]{8cm}
      Erweiterung der Schleifenbedingung:

      \begin{lstlisting}[gobble=8]
        int fun_2 (char *s1, char *s2)
        {
          int result = 1;
          for (int i = 0; s1[i] && s2[i] && result; i++)
            if (s1[i] != s2[i])
              result = 0;
          return result;
        }
      \end{lstlisting}
    \end{minipage}%
    \begin{minipage}[t]{6cm}
      Verwendung von \lstinline{return}:

      \begin{lstlisting}[gobble=8]
        int fun_3 (char *s1, char *s2)
        {
          for (int i = 0; s1[i] && s2[i]; i++)
            if (s1[i] != s2[i])
              return 0;
          return 1;
        }
      \end{lstlisting}
    \end{minipage}
  \end{center}
  \vspace*{-1cm}\goodbreak

  \begin{center}
    \begin{minipage}{9cm}
      Die nebenstehende Lösung unter Verwendung von \lstinline{break}
      ist zwar ebenfalls richtig, aber länger und weniger übersichtlich
      als die beiden anderen Lösungen.

      \smallskip

      Die Datei \gitfile{hp}{20191031}{loesung-1.c} enthält ein Testprogramm
      für alle o.\,a.\ Lösungen.
      Das Programm testet nur die offensichtlichsten Fälle;
      für den Einsatz der Funktionen in einer Produktivumgebung
      wären weitaus umfassendere Tests erforderlich.

      \smallskip

      Das Testprogramm enthält String-Zuweisungen wie z.\,B.\
      \lstinline{s2 = "Apfel"}.
      Dies funktioniert, weil wir damit einen Zeiger (\lstinline{char *s2})
      auf einen neuen Speicherbereich (\lstinline{"Apfel"}) zeigen lassen.
      Eine entsprechende Zuweisung zwischen Arrays
      (\lstinline{char s3[] = "Birne"; s3 = "Pfirsich";)}
      funktioniert \emph{nicht}.
      
    \end{minipage}\hspace*{1cm}%
    \begin{minipage}{6cm}
      \begin{lstlisting}[gobble=8]
        int fun_4 (char *s1, char *s2)
        {
          int result = 1;
          for (int i = 0; s1[i] && s2[i]; i++)
            if (s1[i] != s2[i])
              {
                result = 0;
                break;
              }
          return result;
        }
      \end{lstlisting}
    \end{minipage}
  \end{center}

  \exercise{Programm analysieren}

  Wir betrachten das folgende C-Programm (Datei: \gitfile{hp}{20191031}{aufgabe-2.c}):
  \begin{lstlisting}
    char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}
  \end{lstlisting}
  \vspace{-\medskipamount}
  \begin{itemize}
    \item[(a)]
      Was bewirkt dieses Programm?
    \item[(b)]
      Wofür stehen die Zahlen?
    \item[(c)]
      Ergänzen Sie das Programm derart, daß seine \lstinline{main()}-Funktion
      \lstinline{int main (void)} lautet und eine \lstinline{return}-Anweisung hat,
      wobei die in Aufgabenteil (a) festgestellte Eigenschaft erhalten bleiben soll.
  \end{itemize}

  \solution

  \begin{itemize}
    \item[(a)]
      \textbf{Was bewirkt dieses Programm?}

      Es gibt \emph{seinen eigenen Quelltext\/} aus.

      (Wichtig ist die Bezugnahme auf den eigenen Quelltext.
      Die Angabe\\
      "`Es gibt
      \lstinline|char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}|
      aus"'\\
      genügt insbesondere nicht.)

    \item[(b)]
      \textbf{Wofür stehen die Zahlen?}

      Die 34 steht für ein Anführungszeichen und die 10 für ein
      Zeilenendezeichen (\lstinline{\n}).

      Hintergrund: Um den eigenen Quelltext ausgeben zu können, muß
      das Programm auch Anführungszeichen und Zeilenendezeichen
      ausgeben. Dies geschieht normalerweise mit vorangestelltem
      Backslash: \lstinline{\"} bzw.\ \lstinline{\n}. Um dann aber
      den Backslash ausgeben zu können, müßte man diesem ebenfalls
      einen Backslash voranstellen: \lstinline{\\}. Damit dies nicht
      zu einer Endlosschleife wird, verwendet der Programmierer
      dieses Programms den Trick mit den Zahlen, die durch
      \lstinline{%c} als Zeichen ausgegeben werden.

    \item[(c)]
      \textbf{Ergänzen Sie das Programm derart, daß seine \lstinline{main()}-Funktion
      \lstinline{int main (void)} lautet und eine \lstinline{return}-Anweisung hat,
      wobei die in Aufgabenteil (a) festgestellte Eigenschaft erhalten bleiben soll.}

      Datei: \gitfile{hp}{20191031}{loesung-2.c}
      \begin{lstlisting}[gobble=8]
        char*f="char*f=%c%s%c;int main(void){printf(f,34,f,34,10);return 0;}%c";
        int main(void){printf(f,34,f,34,10);return 0;}
      \end{lstlisting}
      Das Programm ist eine einzige, lange Zeile, die hier nur aus
      Platzgründen als zwei Zeilen abgedruckt wird. Auf das
      Semikolon am Ende der "`ersten Zeile"' folgt unmittelbar -- ohne Leerzeichen --
      das Schlüsselwort \lstinline{int} am Anfang der "`zweiten Zeile"'.

      Mit "`die in Aufgabenteil (a) festgestellte Eigenschaft"' ist
      gemeint, daß das Programm weiterhin seinen eigenen Quelltext
      ausgeben soll. Die Herausforderung dieser Aufgabe besteht
      darin, das Programm zu modifizieren, ohne diese Eigenschaft zu
      verlieren.

      Zusatzaufgabe für Interessierte: Ergänzen Sie das Programm so,
      daß es auch mit \lstinline[style=cmd]{-Wall} ohne Warnungen
      compiliert werden kann.
      
      Hinweis dazu: \lstinline{#include<stdio.h>}
      (ohne Leerzeichen, um Platz zu sparen)
      
      Lösung der Zusatzaufgabe: \gitfile{hp}{20191031}{loesung-2x.c}

  \end{itemize}

  \exercise{Fehlerhaftes Primzahl-Programm}

  \begin{minipage}[t]{5.5cm}
    Das nebenstehende Primzahlsuchprogramm (Datei: \gitfile{hp}{20191031}{aufgabe-3.c})
    soll Zahlen ausgeben, die genau zwei Teiler haben, ist aber fehlerhaft.

    \smallskip

    Korrigieren Sie das Programm derart, daß ein Programm entsteht,
    welches alle Primzahlen kleiner 100 ausgibt.% \points 5
  \end{minipage}\hfill
  \begin{minipage}[t]{9cm}
     \vspace*{-0.5cm}
    \begin{lstlisting}[gobble=6]
      #include <stdio.h>

      int main (void)
      {
        int n, i, divisors;
        for (n = 0; n < 100; n++)
          divisors = 0;
          for (i = 0; i < n; i++)
            if (n % i == 0)
              divisors++;
          if (divisors = 2)
            printf ("%d ist eine Primzahl.\n", n);
        return 0;
      }
    \end{lstlisting}
  \end{minipage}

  \solution

  Beim Compilieren des Beispiel-Programms mit
  \lstinline[style=cmd]{gcc -Wall} erhalten wir die folgende Warnung:
  \begin{lstlisting}[style=terminal]
    aufgabe-2.c:11:5: warning: suggest parentheses around assignment
                      used as truth value [-Wparentheses]
  \end{lstlisting}
  Beim Ausführen gibt das Programm die folgende (falsche) Behauptung aus:
  \begin{lstlisting}[style=terminal]
    100 ist eine Primzahl.
  \end{lstlisting}

  Einen ersten Hinweis auf den Fehler im Programm liefert die Warnung.
  Die Bedingung \lstinline{if (divisors = 2)} in Zeile 11
  steht \emph{nicht\/} für einen Vergleich
  der Variablen \lstinline{divisors} mit der Zahl 2,
  sondern für eine Zuweisung der Zahl 2 an die Variable \lstinline{divisors}.
  Neben dem \emph{Seiteneffekt\/} der Zuweisung gibt \lstinline{divisors = 2}
  den Wert \lstinline{2} zurück.
  Als Bedingung interpretiert, hat \lstinline{2} den Wahrheitswert "`wahr"' ("`true"');
  die \lstinline{printf()}-Anweisung wird daher in jedem Fall ausgeführt.

  Korrektur dieses Fehlers: \lstinline{if (divisors == 2)}
  -- siehe die Datei \gitfile{hp}{20191031}{loesung-2-1.c}.

  \bigskip

  Nach der Korrektur dieses Fehlers compiliert das Programm ohne Warnung,
  gibt aber beim Ausführen die folgende Fehlermeldung aus:
  \begin{lstlisting}[style=terminal]
    Gleitkomma-Ausnahme
  \end{lstlisting}
  (Bemerkung: Bei ausgeschalteter Optimierung
  -- \lstinline[style=cmd]{gcc} ohne \lstinline[style=cmd]{-O} --
  kommt diese Fehlermeldung bereits beim ersten Versuch, das Programm auszuführen.
  Der Grund für dieses Verhalten ist, daß bei eingeschalteter Optimierung
  irrelevante Teile des Programms entfernt und gar nicht ausgeführt werden,
  so daß der Fehler nicht zum Tragen kommt.
  In diesem Fall wurde die Berechnung von \lstinline{divisors} komplett wegoptimiert,
  da der Wert dieser Variablen nirgendwo abgefragt,
  sondern durch die Zuweisung \lstinline{if (divisors = 2)}
  sofort wieder überschrieben wurde.)

  Die Fehlermeldung "`\lstinline[style=terminal]{Gleitkomma-Ausnahme}"'
  ist insofern irreführend, als daß hier gar keine Gleitkommazahlen im Spiel sind;
  andererseits deutet sie auf einen Rechenfehler hin, was auch tatsächlich zutrifft.
  Durch Untersuchen aller Rechenoperationen
  -- z.\,B.\ durch das Einfügen zusätzlicher \lstinline{printf()} --
  finden wir den Fehler in Zeile 9:
  Die Modulo-Operation \lstinline{n % i} ist eine Division,
  die dann fehlschlägt, wenn der Divisor \lstinline{i} den Wert 0 hat.
  Die Fehlerursache ist die bei 0 beginnende \lstinline{for}-Schleife in Zeile 8:
  \lstinline{for (i = 0; i < n; i++)}.

  Korrektur dieses Fehlers: Beginn der Schleife mit \lstinline{i = 1}
  statt \lstinline{i = 0} -- siehe die Datei \gitfile{hp}{20191031}{loesung-2-2.c}.

  \bigskip

  Nach der Korrektur dieses Fehlers gibt das Programm überhaupt nichts mehr aus.

  Durch Untersuchen des Verhaltens des Programms
  -- z.\,B.\ durch das Einfügen zusätzlicher \lstinline{printf()} --
  stellen wir fest, daß die Zeilen 8 bis 12 des Programms nur einmal ausgeführt werden
  und nicht, wie die \lstinline{for}-Schleife in Zeile 6 vermuten ließe, 100mal.
  Der Grund dafür ist, daß sich die \lstinline{for}-Schleife
  nur auf die unmittelbar folgende Anweisung \lstinline{divisors = 0} bezieht.
  Nur diese Zuweisung wird 100mal ausgeführt;
  alles andere befindet sich außerhalb der \lstinline{for}-Schleife.
  (Die Einrückung hat in C keine inhaltliche Bedeutung,
  sondern dient nur zur Verdeutlichung der Struktur des Programms.
  In diesem Fall entsprach die tatsächliche Struktur nicht der beabsichtigten.)

  Korrektur dieses Fehlers:
  geschweifte Klammern um den Inhalt der äußeren \lstinline{for}-Schleife
  -- siehe die Datei \gitfile{hp}{20191031}{loesung-2-3.c}.

  \bigskip

  Nach der Korrektur dieses Fehlers gibt das Programm folgendes aus:
  \begin{lstlisting}[style=terminal]
    4 ist eine Primzahl.
    9 ist eine Primzahl.
    25 ist eine Primzahl.
    49 ist eine Primzahl.
  \end{lstlisting}
  Diese Zahlen sind keine Primzahlen (mit zwei Teilern),
  sondern sie haben drei Teiler.
  Demnach findet das Programm einen Teiler zu wenig.
  (Um diesen Fehler zu finden, kann man sich zu jeder Zahl
  die gefundene Anzahl der Teiler \lstinline{divisors} ausgeben lassen.)

  Der nicht gefundene Teiler ist jeweils die Zahl selbst.
  Dies kommt daher, daß die Schleife
  \lstinline{for (i = 1; i < n; i++)} nur bis \lstinline{n - 1} geht,
  also keine Division durch \lstinline{n} stattfindet.

  Korrektur dieses Fehlers: Schleifenbedingung \lstinline{i <= n}
  statt \lstinline{i < n}
  -- siehe die Datei \gitfile{hp}{20191031}{loesung-2-4.c}.

  \bigskip

  Nach der Korrektur dieses Fehlers verhält sich das Programm korrekt.

  Die Datei \gitfile{hp}{20191031}{loesung-2-4.c} enthält somit das korrigierte Programm.

\end{document}

20191031/hp-uebung-20191031.tex

deleted100644 → 0
+0 −127
Original line number Original line Diff line number Diff line
% hp-uebung-20191031.pdf - Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019  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: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm

\documentclass[a4paper]{article}

\usepackage{pgscript}

\thispagestyle{empty}

\begin{document}

  \thispagestyle{empty}

  \section*{Hardwarenahe Programmierung\\
            Übungsaufgaben -- 31.\ Oktober 2019}

  \exercise{Strings}

  Strings werden in der Programmiersprache C
  durch Zeiger auf \lstinline{char}-Variable realisiert.

  Wir betrachten die folgende Funktion (Datei: \gitfile{hp}{20191031}{aufgabe-1.c}):
  \begin{center}
    \begin{minipage}{8cm}
      \begin{lstlisting}[gobble=8]
        int fun_1 (char *s1, char *s2)
        {
          int result = 1;
          for (int i = 0; s1[i] && s2[i]; i++)
            if (s1[i] != s2[i])
              result = 0;
          return result;
        }
      \end{lstlisting}
    \end{minipage}%
  \end{center}
  \begin{itemize}
    \item[(a)]
      Was bewirkt die Funktion? % \points{3}
    \item[(b)]
      Welchen Sinn hat die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife? % \points{2}
    \item[(c)]
      Was würde sich ändern, wenn die Bedingung "`\lstinline{s1[i] && s2[i]}"'
      in der \lstinline{for}-Schleife\\
      zu "`\lstinline{s1[i]}"' verkürzt würde? % \points{3}
%    \item[(d)]
%      Von welcher Ordnung (Landau-Symbol) ist die Funktion \lstinline{fun_1()}
%      hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen in den Strings
%      -- und warum? % \points{2}
    \item[(d)]
      Schreiben Sie eine eigene Funktion,
      die dieselbe Aufgabe erledigt wie \lstinline{fun_1()}, nur effizienter.
%      und geben Sie die Ordnung (Landau-Symbol) der von Ihnen geschriebenen Funktion an. % \points{5}
  \end{itemize}

  \exercise{Programm analysieren}

  Wir betrachten das folgende C-Programm (Datei: \gitfile{hp}{20191031}{aufgabe-2.c}):
  \begin{lstlisting}
    char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}
  \end{lstlisting}
  \vspace{-\medskipamount}
  \begin{itemize}
    \item[(a)]
      Was bewirkt dieses Programm?
    \item[(b)]
      Wofür stehen die Zahlen?
    \item[(c)]
      Ergänzen Sie das Programm derart, daß seine \lstinline{main()}-Funktion
      \lstinline{int main (void)} lautet und eine \lstinline{return}-Anweisung hat,
      wobei die in Aufgabenteil (a) festgestellte Eigenschaft erhalten bleiben soll.
  \end{itemize}

  \exercise{Fehlerhaftes Primzahl-Programm}

  \begin{minipage}[t]{5.5cm}
    Das nebenstehende Primzahlsuchprogramm (Datei: \gitfile{hp}{20191031}{aufgabe-3.c})
    soll Zahlen ausgeben, die genau zwei Teiler haben, ist aber fehlerhaft.

    \smallskip

    Korrigieren Sie das Programm derart, daß ein Programm entsteht,
    welches alle Primzahlen kleiner 100 ausgibt.% \points 5
  \end{minipage}\hfill
  \begin{minipage}[t]{9cm}
     \vspace*{-0.5cm}
    \begin{lstlisting}[gobble=6]
      #include <stdio.h>

      int main (void)
      {
        int n, i, divisors;
        for (n = 0; n < 100; n++)
          divisors = 0;
          for (i = 0; i < n; i++)
            if (n % i == 0)
              divisors++;
          if (divisors = 2)
            printf ("%d ist eine Primzahl.\n", n);
        return 0;
      }
    \end{lstlisting}
  \end{minipage}

\end{document}

20191031/strings-10.c

deleted100644 → 0
+0 −12
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 137, 13, 117};
  char *a = answer;
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  a -= 4;
  printf ("a: %d %d %d %d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
  return 0;
}

20191031/strings-11.c

deleted100644 → 0
+0 −12
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 65, 66, 117};
  char *a = answer;
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  a -= 4;
  printf ("a: %d %d %d %d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
  return 0;
}

20191031/strings-6.c

deleted100644 → 0
+0 −10
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 137, 13, 117};
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  printf ("Answer: %d\n", answer[0]);
  return 0;
}

20191031/strings-6.s

deleted100644 → 0
+0 −37
Original line number Original line Diff line number Diff line
	.file	"strings-6.c"
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"%s"
.LC1:
	.string	"Answer: %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB11:
	.cfi_startproc
	subq	$40, %rsp
	.cfi_def_cfa_offset 48
	movl	$1963821354, 28(%rsp)
	movabsq	$8583909746840200520, %rax
	movq	%rax, 14(%rsp)
	movl	$1684828783, 22(%rsp)
	movw	$2593, 26(%rsp)
	leaq	14(%rsp), %rsi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movzbl	28(%rsp), %esi
	movsbl	%sil, %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	addq	$40, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE11:
	.size	main, .-main
	.ident	"GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
	.section	.note.GNU-stack,"",@progbits

20191031/strings-7.c

deleted100644 → 0
+0 −10
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 137, 13, 117, 43, 138, 14, 118};
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  printf ("Answer: %d\n", answer[0]);
  return 0;
}

20191031/strings-8.c

deleted100644 → 0
+0 −10
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 137, 13, 117};
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  printf ("Answer: %d %d %d %d\n", answer[0], answer[1], answer[2], answer[3]);
  return 0;
}

20191031/strings-9.c

deleted100644 → 0
+0 −13
Original line number Original line Diff line number Diff line
#include <stdio.h>

int main (void)
{
  volatile char answer[] = {42, 137, 13, 117};
  char *a = answer;
  char hello[14] = "Hello, world!\n";
  printf ("%s", hello);
  printf ("Answer: %d %d %d %d\n", answer[0], answer[1], answer[2], answer[3]);
  a -= 4;
  printf ("a: %d %d %d %d\n", a[0], a[1], a[2], a[3]);
  return 0;
}

20191107/blink-0a.c

deleted100644 → 0
+0 −9
Original line number Original line Diff line number Diff line
#include <avr/io.h>

int main (void)
{
  DDRD = 0x40;   /* binär: 0100 0000 */
  PORTD = 0x00;  /* binär: 0000 0000 */
  while (1);
  return 0;
}

20191107/blink-11.c

deleted100644 → 0
+0 −32
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

volatile uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      _delay_ms (1);
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}

20191107/blink-2.c

deleted100644 → 0
+0 −16
Original line number Original line Diff line number Diff line
#include <avr/io.h>

#define F_CPU 16000000l
#include <util/delay.h>

int main (void)
{
  DDRD = 0x02;
  PORTD = 0x02;
  while (1)
    {
      _delay_ms (250);
      PORTD ^= 0x02;
    }
  return 0;
}

20191107/blink-9.c

deleted100644 → 0
+0 −31
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}
+0 −212
Original line number Original line Diff line number Diff line
% hp-musterloesung-20191107.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019  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: Arrays mit Zahlen, Datum-Bibliothek

\documentclass[a4paper]{article}

\usepackage{pgscript}

\begin{document}

  \section*{Hardwarenahe Programmierung\\
            Musterlösung zu den Übungsaufgaben -- 7.\ November 2019}

  \exercise{Arrays mit Zahlen}

  \begin{minipage}[t]{0.4\textwidth}
    Wir betrachten das folgende Programm\\
    (Datei: \gitfile{hp}{20191107}{aufgabe-1.c}):
    \begin{lstlisting}[gobble=6]
      #include <stdio.h>

      void f (int *s0, int *s1)
      {
        while (*s0 >= 0)
        {
          int *s = s1;
          while (*s >= 0)
            if (*s0 == *s++)
              printf ("%d ", *s0);
          s0++;
        }
        printf ("\n");
      }

      int main (void)
      {
        int a[] = { 10, 4, 3, 7, 12, 0, 1, -1 };
        int b[] = { 7, 14, 0, 8, 9, 22, 10, -1 };
        f (a, b);
        return 0;
      }
    \end{lstlisting}
  \end{minipage}\hfill
  \begin{minipage}[t]{0.55\textwidth}
    \vspace*{-\bigskipamount}
    \begin{enumerate}[\quad(a)]
      \item
        Was bewirkt die Funktion \lstinline{f},\\
        und wie funktioniert sie?
        \points{4}
%      \item
%        Von welcher Ordnung (Landau-Symbol) ist die Funktion?
%        Begründen Sie Ihre Antwort.
%
%        Wir beziehen uns hierbei auf die Anzahl der Vergleiche
%        in Abhängigkeit von der Länge der Eingabedaten \lstinline{s0} und \lstinline{s1}.
%        Für die Rechnung dürfen Sie beide Längen mit $n$ gleichsetzen,
%        obwohl sie normalerweise nicht gleich sind.
%        \points{2}
      \item
        Was passiert, wenn Sie beim Aufruf der Funktion für einen der
        Parameter den Wert \lstinline{NULL} übergeben?
        Begründen Sie Ihre Antwort.
        \points{2}
      \item
        Was kann passieren, wenn Sie das Hauptprogramm wie folgt abändern
        (\gitfile{hp}{20191107}{aufgabe-1c.c})?
        Begründen Sie Ihre Antwort.
        \begin{lstlisting}[gobble=8]
          int main (void)
          {
            int a[] = { 10, 4, 3, 7, 12, 0, 1 };
            int b[] = { 7, 14, 0, 8, 9, 22, 10 };
            f (a, b);
            return 0;
          }
        \end{lstlisting}
        \points{2}
%      \item
%        Beschreiben Sie -- in Worten und/oder als C-Quelltext --, wie
%        sich die Funktion \lstinline{f} effizienter gestalten läßt,
%        wenn man die ihr übergebenen Arrays \lstinline{s0} und
%        \lstinline{s1} als sortiert voraussetzt.
%        \points{5}
%
%        Hinweis: Wie würden Sie als Mensch die Aufgabe erledigen?
%      \item
%        Von welcher
%        Ordnung (Landau-Symbol) ist Ihre effizientere Version der Funktion und warum?
%        \points{2}
    \end{enumerate}
  \end{minipage}

  \solution

  \begin{enumerate}[\quad(a)]
    \item
      \textbf{Was bewirkt die Funktion \lstinline{f}, und wie funktioniert sie?}

      Die Funktion gibt alle Zahlen aus, die sowohl im Array \lstinline{s0}
      als auch im Array \lstinline{s1} vorkommen (Schnittmenge).

      Dies geschieht, indem der Zeiger \lstinline{s0} das gesamte Array durchläuft
      (äußere Schleife).
      Für jedes Element des ersten Arrays durchläuft der Zeiger \lstinline{s}
      das gesamte zweite Array (innere Schleife).
      Auf diese Weise wird jedes Element von \lstinline{s0}
      mit jedem von \lstinline{s1} verglichen und bei Gleichheit ausgegeben.

      Um die Schleifen abbrechen zu können, enthalten beide Arrays
      als Ende-Markierung eine negative Zahl (\lstinline{-1}).

    \item
      \textbf{Was passiert, wenn Sie beim Aufruf der Funktion für einen der
      Parameter den Wert \lstinline{NULL} übergeben?
      Begründen Sie Ihre Antwort.}

      In dem Moment, wo auf den jeweiligen Parameter-Zeiger zugegriffen wird
      (\lstinline{while (*s0 >= 0)} für \lstinline{s0} bzw.\
      \lstinline{int *s = s1; while (*s >= 0)} für \lstinline{s1}),
      kommt es zu einem Absturz (Speicherzugriffsfehler).
      Die Dereferenzierung eines Zeigers mit dem Wert \lstinline{NULL}
      ist nicht zulässig.

    \item
      \textbf{Was kann passieren, wenn Sie das Hauptprogramm wie folgt abändern
      (\gitfile{hp}{20191107}{aufgabe-1c.c})?
      Begründen Sie Ihre Antwort.}

      \begin{minipage}{0.35\textwidth}
        \begin{lstlisting}[gobble=10]
          int main (void)
          {
            int a[] = { 10, 4, 3, 7, 12, 0, 1 };
            int b[] = { 7, 14, 0, 8, 9, 22, 10 };
            f (a, b);
            return 0;
          }
        \end{lstlisting}
      \end{minipage}\hfill
      \begin{minipage}{0.575\textwidth}
        Durch die fehlenden Ende-Markierungen der Arrays
        laufen die Schleifen immer weiter,
        bis sie irgendwann zufällig auf Speicherzellen stoßen,
        die sich als Ende-Markierungen interpretieren lassen (negative Zahlen).
        Dadurch kann es zu einem Lesezugriff auf Speicher kommen,
        für den das Programm kein Lesezugriffsrecht hat,
        also zu einem Absturz (Speicherzugriffsfehler).
      \end{minipage}
  \end{enumerate}

  \exercise{Datum-Bibliothek}

  Schreiben Sie eine Bibliothek (= Sammlung von Deklarationen und Funktionen)
  zur Behandlung von Datumsangaben.

  Diese soll enthalten:
  \begin{itemize}
    \item
      einen \lstinline{struct}-Datentyp \lstinline{date},
      der eine Datumsangabe speichert,
    \item
      eine Funktion \lstinline{void date_print (date *d)}, die ein Datum ausgibt,
    \item
      eine Funktion \lstinline{int date_set (date *d, int day, int month, int year)},
      die ein Datum auf einen gegebenen Tag setzt
      und zurückgibt, ob es sich um ein gültiges Datum handelt (0 = nein, 1 = ja),
    \item
      eine Funktion \lstinline{void date_next (date *d)},
      die ein Datum auf den nächsten Tag vorrückt.
  \end{itemize}

  Schreiben Sie auch ein Programm, das die o.\,a.\ Funktionen testet.

  \solution

  Die Datei \gitfile{hp}{20191107}{loesung-2.c}
  enthält die Bibliothek zusammen mit einem Test-Programm.

  Eine detaillierte Anleitung,
  wie man auf die Funktion \lstinline{date_next()} kommt,
  finden Sie im Skript zur Lehrveranstaltung, Datei \gitfile{hp}{script}{hp-2019ws.pdf},
  ab Seite 29.

  (Die Vorgehensweise,
  die Bibliothek und das Hauptprogramm in dieselbe Datei zu schreiben,
  hat den Nachteil,
  daß man die Bibliothek in jedes weitere Programm, das sie benutzt,
  kopieren und auch dort aktuell halten muß.
  Eine sinnvollere Lösung wird demnächst in der Vorlesung vorgestellt werden.)

\end{document}

20191107/loesung-2.c

deleted100644 → 0
+0 −109
Original line number Original line Diff line number Diff line
#include <stdio.h>

typedef struct
{
  char day, month;
  int year;
}
date;

int is_leap_year (int year)
{
  if (year % 4 == 0)
    if (year % 100 == 0)
      if (year % 400 == 0)
        return 1;
      else
        return 0;
    else
      return 1;
  else
    return 0;
}

int days_in_month (int month, int year)
{
  if (month == 2)
    if (is_leap_year (year))
      return 29;
    else
      return 28;
  else if (month == 4 || month == 6 || month == 9 || month == 11)
    return 30;
  else
    return 31;
}

void date_print (date *d)
{
  printf ("%02d.%02d.%04d", d->day, d->month, d->year);
}

int date_set (date *d, char day, char month, int year)
{
  d->year = year;
  if (month > 0 && month <= 12)
    d->month = month;
  else
    return 0;
  if (day > 0 && day <= days_in_month (month, year))
    d->day = day;
  else
    return 0;
  return 1;
}

void date_next (date *d)
{
  d->day++;
  if (d->day > days_in_month (d->month, d->year))
    {
      d->month++;
      d->day = 1;
      if (d->month > 12)
        {
          d->year++;
          d->month = 1;
        }
    }
}

void check (char day, char month, int year)
{
  date d;
  if (date_set (&d, day, month, year))
    {
      date_print (&d);
      printf (" --> ");
      date_next (&d);
      date_print (&d);
      printf ("\n");
    }
  else
    printf ("%02d.%02d.%04d: invalid date\n", day, month, year);
}

int main (void)
{
  check (6, 11, 2018);
  check (29, 11, 2018);
  check (30, 11, 2018);
  check (31, 11, 2018);
  check (29, 12, 2018);
  check (30, 12, 2018);
  check (31, 12, 2018);
  check (28, 2, 2016);
  check (29, 2, 2016);
  check (30, 2, 2016);
  check (28, 2, 2015);
  check (29, 2, 2015);
  check (30, 2, 2015);
  check (31, 12, 2008);
  check (28, 2, 2000);
  check (29, 2, 2000);
  check (30, 2, 2000);
  check (28, 2, 1900);
  check (29, 2, 1900);
  check (30, 2, 1900);
  return 0;
}

20191107/string-ops-10.c

deleted100644 → 0
+0 −15
Original line number Original line Diff line number Diff line
#include <stdio.h>
#include <string.h>

int main (void)
{
  char *anton1 = "Anton";
  char *anton2 = "anton";
  char *zacharias1 = "Zacharias";
  char *zacharias2 = "zacharias";

  printf ("%d\n", strcmp (anton2, zacharias1));
  printf ("%d\n", strcmp (anton2, zacharias2));

  return 0;
}

20191107/string-ops-13.c

deleted100644 → 0
+0 −22
Original line number Original line Diff line number Diff line
#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[] = "Huber ";
  strcat (buffer, anton);
  strcat (buffer, anton);
  strcat (buffer, anton);
  strcat (buffer, anton);
  strcat (buffer, anton);
  printf ("%s\n", buffer);

  return 0;
}

20191107/string-ops-14.c

deleted100644 → 0
+0 −22
Original line number Original line Diff line number Diff line
#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[20] = "Huber ";
  strncat (buffer, anton, 20);
  strncat (buffer, anton, 20);
  strncat (buffer, anton, 20);
  strncat (buffer, anton, 20);
  strncat (buffer, anton, 20);
  printf ("%s\n", buffer);

  return 0;
}

20191107/string-ops-7.c

deleted100644 → 0
+0 −25
Original line number Original line Diff line number Diff line
#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 anton2[] = "Anton";
  if (anton == anton2)
    printf ("gleich\n");
  else
    printf ("ungleich\n");
/*
  char buffer[100] = "Huber ";
  strcat (buffer, anton);
  printf ("%s\n", buffer);
*/

  return 0;
}

20191114/blink-0a.c

deleted100644 → 0
+0 −9
Original line number Original line Diff line number Diff line
#include <avr/io.h>

int main (void)
{
  DDRD = 0x40;   /* binär: 0100 0000 */
  PORTD = 0x00;  /* binär: 0000 0000 */
  while (1);
  return 0;
}

20191114/blink-10.c

deleted100644 → 0
+0 −31
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

volatile uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}

20191114/blink-11.c

deleted100644 → 0
+0 −32
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

volatile uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      _delay_ms (1);
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}

20191114/blink-8.c

deleted100644 → 0
+0 −20
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

ISR (INT0_vect)  /* PD2 */
{
  PORTD ^= 0x40;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xff;   /* binär: 1111 1111 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1);
  return 0;
}
+0 −1
Original line number Original line Diff line number Diff line
README: Logische und bitweise Und-Verknüpfung (rechts), einzelnes Bit auf 1 setzen (links)
+0 −1
Original line number Original line Diff line number Diff line
README: Einzelnes Bit auf 1 (rechts) bzw. auf 0 (links) setzen
+0 −1
Original line number Original line Diff line number Diff line
README: Einzelnes Bit auf 0 setzen (rechts) bzw. umklappen (Mitte) bzw. abfragen (links)

20191121/blink-0a.c

deleted100644 → 0
+0 −9
Original line number Original line Diff line number Diff line
#include <avr/io.h>

int main (void)
{
  DDRD = 0x40;   /* binär: 0100 0000 */
  PORTD = 0x00;  /* binär: 0000 0000 */
  while (1);
  return 0;
}

20191121/blink-10.c

deleted100644 → 0
+0 −31
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

volatile uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}

20191121/blink-11.c

deleted100644 → 0
+0 −32
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define F_CPU 16000000l
#include <util/delay.h>

volatile uint8_t key_pressed = 0;

ISR (INT0_vect)  /* PD2 */
{
  key_pressed = 1;
}

int main (void)
{
  cli ();
  EICRA = 1 << ISC00 | 1 << ISC01;  /* INT0: steigende Flanke */
  EIMSK = 1 << INT0;  /* INT0 einschalten */
  sei ();
  DDRD = 0xfb;   /* binär: 1111 1011 */
  PORTD = 0x60;  /* binär: 0100 0000 */
  while (1)
    {
      while (!key_pressed)
        ;  /* just wait */
      _delay_ms (1);
      PORTD ^= 0x40;
      key_pressed = 0;
    }
  return 0;
}

20191121/blink-3.c

deleted100644 → 0
+0 −17
Original line number Original line Diff line number Diff line
#include <avr/io.h>

#define F_CPU 16000000
#include <util/delay.h>

int main (void)
{
  DDRD = 0x01;
  PORTD = 0x01;
  while (1)
    {
      while ((PIND & 0x02) == 0)
        ; /* just wait */
      PORTD ^= 0x01;
    }
  return 0;
}

20191121/blink-5.c

deleted100644 → 0
+0 −19
Original line number Original line Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>

ISR (TIMER0_COMPB_vect)
{
  PORTD ^= 0x40;
}

int main (void)
{
  cli ();
  TCCR0B = (1 << CS01) | (1 << CS00);  /* Takt durch 64 dividieren */
  TIMSK0 = 1 << OCIE0B;  /* Interrupt einschalten */
  sei ();
  DDRD = 0xfd;   /* binär: 1111 1101 */
  PORTD = 0x40;  /* binär: 0100 0000 */
  while (1);
  return 0;
}