Einführung in die Verwendung der Standardnotation für Werte in C++ im Rahmen der Lehre der Programmiersprache C++. (C++, Standardnotation, Funktionsaufruf, Funktionsaufrufe, Werte.), Lektion, Seite 722239
https://www.purl.org/stefan_ram/pub/c++_standardnotation_fuer_werte (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Funktionen in C++ 

Aufrufe im Ausdruckrahmen

Ein Wert wurde bisher durch ein Literal wie »65« oder einen Namen wie »INT_MAX« angegeben.

Das folgende Programm zeigt eine weitere Möglichkeit  der Festlegung eines Wertes.

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand() << "\n"s; }

::std::cout
41

Ein Aufrufausdruck hat die Form »A ()«, wobei »A « ein Ausdruck ist, der ein Programm angibt.

Bei der Auswertung eines Aufrufausdrucks wird das durch den Ausdruck vor den Klammern angegebene Programm gestartet. Dieses legt dann den Typ und den Wert des Aufrufausdruckes fest.

C++ 
::std::rand()
auf deutsch (kurz):
rand -Aufrufausdruck“
auf deutsch (erklärend):
der von der Ausführung des Programmes »::std::rand« festgelegte Wert

Bei der Auswertung eines Aufrufausdrucks, wie »::std::rand()«, wird das Programm »::std::rand« gestartet und ausgeführt. Man sagt aber meistens dazu nicht „das Programm  »::std::rand« wird ausgeführt.“, sondern „die Funktion  »::std::rand« wird aufgerufen.“. Programme, die auf die hier gezeigte Weise gestartet und ausgeführt werden können, nennt man also Funktionen. Den Start eines solchen Programms bezeichnet man auch als Aufruf  der Funktion. Aber auch ein Aufrufausdruck wird kurs als „Aufruf “ bezeichnet.

Wir hatten zuvor bereits Operatoren  kennengelernt, auch hinter diesen verbergen sich eigentlich Programme, die bei der Auswertung eines Operatorausdruck gestartet werden.

»::std::rand()« ist ein Ausdruck, dessen Typ und Wert durch das Programm »::std::rand« festgelegt wird.

Die ausgegebene Zahl ist insofern „zufällig“, als vor dem ersten Programmstart nicht bekannt ist, welche Zahl ausgegeben werden wird. Es ist aber in der Regel so, daß bei weiteren Programmstarts immer wieder dieselbe Zahl ausgegeben wird.

Später wird behandelt werden, wie auch weniger vorhersagbare Zufallszahlen erzeugt werden können.

Der oben verwendete Aufrufausdruck »::std::rand()« besteht aus einem Namen (hier »::std::rand«) und einem Paar runder Klammern »()«.

Jede einzelne Aufrufklammer ist eine lexikalische Einheit für sich, so daß die Bedeutung eines Programms sich nicht ändert, wenn die Klammern mit Leerraum umgeben sind, wie in »::std::rand ( )«. Auch der Bereichsauflösungsoperator  (oder – kurz – Bereichsoperator  [Martin Hitz]) »::« ist eine lexikalische Einheit, daher ist auch die Schreibweise »:: std :: rand()« möglich.

Bestimmte Laufzeitwerte werden Funktionen  genannt. Der Name in einem Aufruf muß ein Name einer Funktion sein. Der Name »::std::rand« ist auch tatsächlich ein Name einer Funktion.

Man sagt, daß ein Aufrufausdruck ein Aufruf der Funktion, deren Name vor den Klammern steht, sei. Bei »::std::rand()« handelt es sich also um einen Aufruf der Funktion »::std::rand«.

Der kleinstmögliche Wert des Aufrufausdrucks »::std::rand()« ist »0«, der größtmögliche Wert ist der Wert des Namens »RAND_MAX«, der von der verwendeten C++ -Implementation abhängt, ist aber mindestens 32767 ist.

RAND_MAX

#include <cstdlib>

RAND_MAX

an integer constant expression that is the maximum value returned by the rand function

Der Wert wird im Falle eines Aufrufs oft erst während  der Ausführung des Programms ermittelt. Der ermittelte Wert wird alsdann von dem Ausdruckrahmen ausgegeben.

Das folgende Programm gibt (etwas vereinfacht gesagt) die Funktion »::std::rand« selber  aus (ohne, daß diese aufgerufen wird, wie man am Fehlen der Aufrufklammern sind).

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand << "\n"s; }

::std::cout
1

Man sieht, daß ein Funktionsname zunächst nur ein Wertname ist und ein Aufruf erst durch Verwendung des Aufrufoperators erfolgt.

Eine Funktion kann von C++  nicht ausgegeben werden; C++  wandelt die Funktion hier automatisch in etwas um, das es ausgeben kann, was hier – etwas vereinfacht gesagt – die Zahl 1 ist. So ergibt, der Versuch irgendeine Funktion auszugeben, in C++  stets nur die Ausgabe »1«.

Eine mögliche Aussprache von “rand ” ist /ˈrænd./.

Dokumentation von Funktionen

Die vordefinierten Funktionen der Programmiersprache C++  sind in der Spezifikation von C++  (ISO-Norm) beschrieben oder – wie man auch sagt – „dokumentiert“. Diese Dokumentation findet man daneben auch in C++ -Nachschlagewerken auf englisch oder auf deutsch, wie sie etwa in Buchform oder über Datennetze veröffentlicht werden.

Funktionen werden in C++  in etwa wie in dem folgenden Beispiel dokumentiert.

In der Dokumentation des Aufrufs »rand()« steht der Typ »int« dieses Aufrufs vor dem Namen der Funktion.

Dokumentation von »::std::rand()« (gekürzt und überarbeitet)

#include <cstdlib>

int rand();

Ergibt eine Pseudo-Zufallszahl zwischen »0« (einschließlich) und »RAND_MAX« (einschließlich)

Die voranstehende Dokumentation gibt an, daß eine Übersetzungseinheit die #include -Direktive "#include <cstdlib>" am Anfang der Übersetzungseinheit verwenden muß, wenn in der Übersetzungseinheit der Namen »::std::rand« in dem in der Dokumentation beschriebenem Sinne verwendet werden soll.

Vor die Beschreibung des Wertes eines Aufrufs der Funktion wird manchmal „Wert:“ geschrieben.

Außerdem zeigt die Proklamation  (wie solch die kurze Dokumentation »int rand();« hier genannt wird) ein Aufrufmuster "rand()" an (man sollte aber tatsächlich schreiben: »::std::rand«), und gibt an, daß solch ein Aufruf einen Wert vom Datentyp "int" hat. Die Angabe »int« vor dem Namen »rand« besagt also, daß ein Aufrufausdruck dieser Funktion den Typ »int« hat. Dieser Typ wird manchmal auch Ergebnistyp  der Funktion genannt.

Traditionell wird solch eine Proklamation oft mit einem Semikolon ";" abgeschlossen. Das heißt aber nicht, daß in einem Quelltext hinter solch einem Aufruf jedesmal ein Semikolon stehen muß.

Schließlich endet die Dokumentation mit einer Erklärung der Bedeutung von "::std::rand()". Dabei wird erklärt, daß der Wert des Aufrufs dieser Funktion stets zwischen 0 (einschließlich) und dem Wert von »RAND_MAX« (einschließlich) liegt.

Wir schreiben bis auf weiteres Typen (wie »double«) nicht  in den Quelltext. Die Typen dienen uns hier lediglich zur Beschreibung von Funktionen.

Man beachte, daß die Zeile »int rand();« nicht  in dem obigen Programm vorkommt, welches die Funktion »::std::rand« aufruft. Die Dokumentation ist also nicht so zu verstehen, daß man sie in das Programm kopiert! Dokumentation darf nicht mit einem C++ -Programm verwechselt werden. Die Dokumentation ist nicht  dafür gedacht, in ein C++ -Programm kopiert zu werden. Die Dokumentation ist dafür gedacht, bei Bedarf vom Programmierer gelesen zu werden.

Rückgabewerte

Wenn der Aufrufausdruck »::std::rand()« in den Ausdruckrahmen geschrieben wird, so wird dadurch bestimmt, daß der auszugebende Wert bei der Ausführung des Programms von der Funktion »::std::rand« ermittelt werden soll. Der Aufruf legt also eine bestimmte Funktion fest und diese legt dann ihrerseits den auszugebenden Wert fest.

Dieser Wert ergibt sich dann dadurch, daß gegen Ende des Aufrufvorgangs bei der Ausführung des Aufrufs »::std::rand()« ein Wert für diesen Aufrufausdruck festgelegt wird.

In dem folgenden Beispiel einer Auswertung des Ausdrucks »::std::rand()« wurde als auszugebender Wert beispielsweise 41 festgelegt.

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand() << "\n"s; }

::std::cout
41

Man sagt dazu auch manchmal, daß diese Operation den auszugebenden Wert liefere. Oder man sagt allgemein, daß sie einen Wert liefere  oder ergebe. Diesen Wert kann man auch als das Ergebnis  (oder Resultat ) der Operation »rand()« bezeichnen.

Wird die Kontrolle über den Rechner nun von unserem Hauptprogramm an den Aufruf »rand()« übergeben, so kehrt die Kontrolle normalerweise nach einer Weile wieder aus diesem Aufruf »rand()« zurück. Weil gleichzeitig mit dieser Rückkehr auch der Argumentwert geliefert wird, sagt man auch, daß er zusammen mit der Kontrolle vom Aufruf zurückgegeben  werde, und bezeichnet ihn auch als Rückgabewert. (Der Rückgabewert von »rand()« wird danach vom Ausgabeanweisungsrahmen  »::std::cout << << "\n";« ausgegeben.) Am Ende der Ausführung eines Aufrufs steht also die Rückgabe der Kontrolle und eines eventuellen Rückgabewertes an jene Stelle »«, von der aus dieser Aufruf aufgerufen wurde.

Übergabe und Rückgabe der Kontrolle zur Laufzeit mit Wertrückgabe
.-------------------------------------.
| Hauptprogramm----. |
| | |
| V |
| .---------------. |
| | Unterprogramm | |
| '---------------' |
| | |
| | |
|<-----------------' |
| Rueckgabewert |
| |
'-------------------------------------'
»main« und »::std::rand« bei der oben gezeigten Ausführung
.-------------------------------------.
| main-------------. |
| | |
| V |
| .---------------. |
| | ::std::rand() | |
| '---------------' |
| | |
| | |
|<-----------------' |
| 41 |
| |
'-------------------------------------'

In dem folgenden Protokoll einer Ausführung des Aufrufs »::std::rand()« ist abzulesen, daß bei der protokollierten Ausführung als auszugebender Wert zur Laufzeit beispielsweise 41 festgelegt wurde.

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand() << "\n"s; }

::std::cout
41

Diesen Sachverhalt formuliert man auch folgendermaßen:

Abstrakter sagt man unter Ersetzung der Zahl 41 durch die Beschreibung „eine Zufallszahl“ von der Funktion (statt vom Aufruf):

Falsch ist die Verwendung dieser Verben (wie „zurückgeben“) im Zusammenhang mit Ausdrücken: Ein Ausdruck gibt  keinen Wert zurück, er hat  einen Wert. Beispielsweise gibt die Funktion  »::std::rand« eine Zufallszahl zurück, aber der Aufrufausdruck  »::std::rand()« hat  eine Zufallszahl als Wert.

Zusammenspiel mit Operatoren

Prioritätsstufen (weiter oben = höhere Priorität)

()

()

-

* …, …/

+ …, … -

Ein Aufruf darf auch als Operand eines Operators  verwendet werden.

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << -::std::rand() << "\n"s; }

::std::cout
-41
main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout <<( ::std::rand() )<< "\n"s; }

::std::cout
41
main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand()/10. << "\n"s; }

::std::cout
4.1
main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout << ::std::rand() - 10. << "\n"s; }

::std::cout
31

Der Funktionsname »::std::rand« ist ein Ausdruck und kann daher auch eingeklammert werden.

main.cpp

#include <iostream> // ::std::cout
#include <ostream> // <<
#include <string> // "s
#include <cstdlib> // ::std::rand

using namespace ::std::literals;

int main() { ::std::cout <<( ::std::rand )() << "\n"s; }

::std::cout
41

Kennzahlen für Zeichen

Im folgenden wird manchmal eine Zuordnung von Kennzahlen zu Schriftzeichen gemäß der folgenden Tabelle angenommen.

Tabelle

Zahl Zeichen Beschreibung

10 Zeilenende

48 0 Ziffer 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9

65 A 
66 B 
67 C 
68 D 
69 E 
70 F 
71 G 
72 H 
73 I 
74 J 
75 K 
76 L 
77 M 
78 N 
79 O 
  80 P 
  81 Q 
  82 R 
  83 S 
  84 T 
  85 U 
  86 V 
  87 W 
  88 X 
  89 Y 
  90 Z

  97 a 
  98 b 
  99 c 
 100 d 
 101 e 
 102 f 
 103 g 
 104 h 
 105 i 
 106 j 
 107 k 
 108 l 
 109 m 
 110 n 
 111 o 
 112 p  
 113 q  
 114 r  
 115 s  
 116 t  
 117 u  
 118 v  
 119 w  
 120 x  
 121 y  
 122 z

Diese Zuordnung ist aber nicht durch C++  festgelegt, sondern hängt von verschiedenen Umständen ab, etwa dem Betriebsystem (der Umgebung) unter dem das Programm läuft. Die obenstehende Zuordnung findet sich aber häufig und wird deshalb im weiteren Verlauf des Kurses zugrundegelegt werden.

Die Eingabetaste

Die Eingabetaste ist die Taste, mit welcher Eingaben und Absätze abgeschlossen werden. Auf ihr befindet sich ein nach links weisender Pfeil „↵“, welcher rechts mit einer nach oben weisenden Linie abgeschlossen ist.

Eine Eingabetaste

         .---------------.
| |
| |
.--------' |
| | |
| Enter <--' |
| |
'------------------------'

Eine Eingabetaste

.--------.
| |
| | |
| <--' |
| |
'--. |
| |
| |
| |
| |
'-----'

Übungsaufgaben

/   Selbständiges Schreiben von Programmen

Im folgenden findet sich die Dokumentation einer Funktion der Standardbibliothek.
Zum besseren Verständnis dieser Übung sei vorangeschickt: Für die erfolgreiche Bearbeitung dieser Übung ist es nicht nötig zu verstehen, was eine „Rundungsrichtung“ ist. Weil diese Funktion hier nur als Beispiel einer Funktion dient, aber die Behandlung des Themas der Rundungsrichtungen an dieser Stelle im Kurs ansonsten noch zu früh wäre, wird hier bewußt auf weitere Erklärungen der Bedeutung von Rundungsrichtungen verzichtet.
Dokumentation von »::std::fegetround()« (gekürzt und überarbeitet)

#include <cfenv>

int fegetround();

die aktuelle Rundungsrichtung
Übungsfragen:
  • Welchen Typ  hat der Ausdruck »::std::fegetround()«?
  • Welche include-Direktive wird am Anfang des Programms benötigt, wenn der Ausdruck »::std::fegetround« darin verwendet werden soll?
Eine Übungsaufgabe:
  • Schreiben Sie ein C++ -Programm, welches das Ergebnis eines Aufrufs der Funktion »::std::fegetround()« ausgibt.

/   Anwendung der Funktion »::std::getchar«

Häufiger Fehler Wer bei der Bearbeitung der folgenden Aufgaben die mittlere Zeile der Dokumentation in das Programm kopiert, macht wahrscheinlich einen Fehler. Die mittlere Zeile der Dokumentation soll nicht  kopiert werden. Sie gibt dem Programmierer Informationen über eine Funktion, aufgrund derer die Funktion dann richtig in ein Programm eingebaut werden kann. Dieser Einbau geschieht aber normalerweise nicht  dadurch, daß die mittlere Zeile der Dokumentation einfach in das Programm kopiert wird.
Im folgenden findet sich die Dokumentation einer Funktion der Standardbibliothek.
Zum besseren Verständnis der Dokumentation sei vorangeschickt: Jedes Schriftzeichen hat im Computer eine bestimmte Kennzahl, durch welche es eindeutig identifiziert wird, das Schriftzeichen »V« hat beispielsweise bei vielen Computern die Kennzahl 86.
Die Funktionen »getchar« wird in C++  in etwa wie in dem folgenden Beispiel dokumentiert.
Dokumentation von »::std::getchar()« (gekürzt, teilweise übersetzt und überarbeitet)

#include <cstdio>

int getchar();

Einlesen eines Zeichens von der Konsole.
Wert: Die Kennzahl des nächsten von der Konsole eingelesenen Zeichens

Mit der Standardfunktion "::std::getchar" wird ein Zeichen von der Konsole eingelesen. (Das setzt voraus, daß beim Lauf des Programmes mindestens ein Zeichen eingeben wird und danach die Zeile durch Betätigung der Eingabetaste abgeschlossen wird.)

Der Wert eines Aufrufs dieser Funktion ist die Kennzahl des eingegebenen Zeichens.

Welche include-Direktive wird am Anfang des Programms benötigt, wenn der Ausdruck »::std::getchar« darin verwendet werden soll?

Welchen Typ hat der Wert eines Aufrufs dieser Funktion, also welchen Typ  hat der Aufruf »::std::getchar()«?

Übungsaufgabe:

Schreiben Sie ein C++ -Programm, welches das Ergebnis eines Aufrufs der Funktion »::std::getchar« ausgibt. (Beim Ausprobieren ist zu bedenken, daß das Programm auf die Eingabe eines Zeichens wartet. Oft werden Zeichen erst nach Drücken der Eingabetaste an das Programm weitergeleitet.) Mit anderen Worten: Geben Sie durch Verwendung der Funktion »::std::getchar« in einer C++ -Übersetzungseinheit, die Kennzahl eines eingegebenen Zeichens aus!

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722239 stefan_ram:722239 C++, Standardnotation, Funktionsaufruf, Funktionsaufrufe, Werte. Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722239, slrprddef722239, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/c++_standardnotation_fuer_werte