Wertnamen in C (Wertnamen in C), Lektion, Seite 722924
https://www.purl.org/stefan_ram/pub/wertnamen_c (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C-Kurs

Wertnamen in C

Einführendes Beispiel

In dem folgenden Programmbeispiel wird ein Name  als Ausdruck verwendet.

main.c

#include <stdio.h> /* printf */
#include <errno.h> /* errno */

int main( void )
{ printf
( "%d\n", errno ); }

stdout
0

(Die Bedeutung von »errno« ist hier nicht wichtig.)

Syntax

Ein einfacher Name  oder Bezeichner, wie beispielsweise »errno«, ist (etwas vereinfacht gesagt) eine Folge von Zeichen, die mit einem Buchstaben beginnt, dem weitere Buchstaben oder Ziffern direkt folgen können. An Stelle eines Buchstabens ist auch der Grundstrich »_« erlaubt.

Ein Bezeichner ist eine lexikalische Einheit.

Bezeichner
a
A
Haus
Haus2
HAUS_2
Morphologische Diagramme (vereinfacht)

Bezeichner .----------------------------------------.
.------------------------. | .-----------------------. v
|-|--->| Bezeichnerstartzeichen |---'---.--->| Bezeichnerrestzeichen |---:---'--->|-|
'------------------------' ^ '-----------------------' |
'--------------------------------'

Bezeichnerstartzeichen
.-----------.
|-|---.--->| Buchstabe |---.--->|-|
| '-----------' |
| .-. |
'------->( _ )-------'
'-'

Bezeichnerrestzeichen
.------------------------.
|-|---.--->| Bezeichnerstartzeichen |---.--->|-|
| '------------------------' |
| .------------------------. |
'--->| Dezimalziffer |---'
'------------------------'

Buchstabe
.----------.
|-|---.--->| Majuskel |---.--->|-|
| '----------' |
| .----------. |
'--->| Minuskel |---'
'----------'

Majuskel
.-.
|-|---.--->( A )---.--->|-|
| '-' ^
| .-. |
'--->( B )---'
| '-' ^
| .-. |
'--->( C )---'
| '-' ^
| .-. |
'--->( D )---'
| '-' ^
| .-. |
'--->( E )---'
| '-' ^
| .-. |
'--->( F )---'
| '-' ^
| .-. |
'--->( G )---'
| '-' ^
| .-. |
'--->( H )---'
| '-' ^
| .-. |
'--->( I )---'
| '-' ^
| .-. |
'--->( J )---'
| '-' ^
| .-. |
'--->( K )---'
| '-' ^
| .-. |
'--->( L )---'
| '-' ^
| .-. |
'--->( M )---'
| '-' ^
| .-. |
'--->( N )---'
| '-' ^
| .-. |
'--->( O )---'
| '-' ^
| .-. |
'--->( P )---'
| '-' ^
| .-. |
'--->( Q )---'
| '-' ^
| .-. |
'--->( R )---'
| '-' ^
| .-. |
'--->( S )---'
| '-' ^
| .-. |
'--->( T )---'
| '-' ^
| .-. |
'--->( U )---'
| '-' ^
| .-. |
'--->( V )---'
| '-' ^
| .-. |
'--->( W )---'
| '-' ^
| .-. |
'--->( X )---'
| '-' ^
| .-. |
'--->( Y )---'
| '-' ^
| .-. |
'--->( Z )---'
'-'

Minuskel
.-.
|-|---.--->( a )---.--->|-|
| '-' ^
| .-. |
'--->( b )---'
| '-' ^
| .-. |
'--->( c )---'
| '-' ^
| .-. |
'--->( d )---'
| '-' ^
| .-. |
'--->( e )---'
| '-' ^
| .-. |
'--->( f )---'
| '-' ^
| .-. |
'--->( g )---'
| '-' ^
| .-. |
'--->( h )---'
| '-' ^
| .-. |
'--->( i )---'
| '-' ^
| .-. |
'--->( j )---'
| '-' ^
| .-. |
'--->( k )---'
| '-' ^
| .-. |
'--->( l )---'
| '-' ^
| .-. |
'--->( m )---'
| '-' ^
| .-. |
'--->( n )---'
| '-' ^
| .-. |
'--->( o )---'
| '-' ^
| .-. |
'--->( p )---'
| '-' ^
| .-. |
'--->( q )---'
| '-' ^
| .-. |
'--->( r )---'
| '-' ^
| .-. |
'--->( s )---'
| '-' ^
| .-. |
'--->( t )---'
| '-' ^
| .-. |
'--->( u )---'
| '-' ^
| .-. |
'--->( v )---'
| '-' ^
| .-. |
'--->( w )---'
| '-' ^
| .-. |
'--->( x )---'
| '-' ^
| .-. |
'--->( y )---'
| '-' ^
| .-. |
'--->( z )---'
'-'

Dezimalziffer

.-.
|-|---.--->( 0 )---.--->|-|
| '-' ^
| .-. |
'--->( 1 )---'
| '-' ^
| .-. |
'--->( 2 )---'
| '-' ^
| .-. |
'--->( 3 )---'
| '-' ^
| .-. |
'--->( 4 )---'
| '-' ^
| .-. |
'--->( 5 )---'
| '-' ^
| .-. |
'--->( 6 )---'
| '-' ^
| .-. |
'--->( 7 )---'
| '-' ^
| .-. |
'--->( 8 )---'
| '-' ^
| .-. |
'--->( 9 )---'
'-'

Neue, erweiterte vereinfachte Syntax
Ausdruck
.------------.
---.----------->| Literal |---------------------------.---->
| '------------' |
| .-. .------------. |
'--->( - )-->| Ausdruck |---------------------------'
| '-' '------------' |
| .------------. |
'----------->| Bezeichner |---------------------------'
| '------------' |
| .-. .------------. |
'--->( + )-->| Ausdruck |---------------------------'
| '-' '------------' |
| .-. .------------. .-. |
'--->( ( )-->| Ausdruck |-->( ) )-------------------'
| '-' '------------' '-' |
| .------------. .-. .----------. |
'----------->| Ausdruck |-->( / )-->| Ausdruck |----'
| '------------' '-' '----------' |
| .------------. .-. .----------. |
'----------->| Ausdruck |-->( + )-->| Ausdruck |----'
| '------------' '-' '----------' |
| .------------. .-. .----------. |
'----------->| Ausdruck |-->( - )-->| Ausdruck |----'
| '------------' '-' '----------' |
| .------------. .-. .----------. |
'----------->| Ausdruck |-->( * )-->| Ausdruck |----'
'------------' '-' '----------'

Semantik

Wir haben schon gesehen, daß eine Zahl im Quelltext durch ein Literal  angegeben werden kann.

main.c

#include <stdio.h> /* printf */

int main( void )
{ printf
( "%d\n", 32767 ); }

stdout
32767

Eine Zahl kann jedoch auch durch einen Namen angegeben werden, den wir in diesem Fall auch Zahlennamenausdruck  oder kurz Zahlennamen  nennen. (In diesem Fall ist damit aber nicht gemeint, daß ein Name immer für dieselbe Zahl stehen muß. Die Zahl wurde dem Name willkürlich zugeordnet; daher kann diese Zuordnung auch in einem anderen Fall für denselben Namen wieder eine andere sein.)

main.c

#include <stdio.h> /* printf */
#include <errno.h> /* errno */

int main( void )
{ printf
( "%d\n", errno ); }

stdout
0

Groß- und Kleinschreibung

Die Groß- und Kleinschreibung  ist signifikant. Das heißt, daß »abc« beispielsweise als ein anderer  Name angesehen wird als »aBc«.

Die implementationsdefinierten Typgrößen

Die Größe des Wertebereichs der numerischen Datentypen ist implementationsdefiniert.

Das heißt, daß jede C -Implementation es selber festlegen kann, wie groß der kleinste beziehungsweise der größte Wert des Datentyps »int« ist. Jedoch muß der kleinste Wert kleiner als »[-32766]« und der größte Wert größer als »[32766]« sein.

main.c

#include <stdio.h> /* printf */
#include <limits.h> /* INT_MIN */

int main( void )
{ printf
( "%d\n", INT_MIN ); }

Protokoll
-2147483648
main.c

#include <stdio.h> /* printf */
#include <limits.h> /* INT_MIN */

int main( void )
{ printf
( "%d\n", INT_MAX ); }

Protokoll
2147483647
N2176 5.2.4.2.1 Sizes of integer types <limits.h>, Absatz 1, Satz 3
Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.

INT_MIN -32767

INT_MAX +32767

C  ist eine abstrakte Programmiersprache. Das heißt, daß viele Details durch die Norm nicht genau festgelegt sind, sondern nur ein gewisser Bereich vorgegeben wird, in dem sie sich bewegen dürfen. Ein Programmierer der portable Programme schreiben will, darf nie vergessen, daß viele Eigenschaften der Programmiersprache nicht durch die von ihm zur Entwicklung verwendete Implementation festgelegt sind, sondern durch die Sprachnorm. Ein Programm, das voraussetzt, daß »[INT_MAX]« gleich »[2147483647]« ist, würde beispielsweise möglicherweise nicht  auf allen Implementationen das gewünschte Verhalten zeigen.

Aufgrund dieser Abstraktheit ist es schwer, C  zu erlernen und zu beherrschen. Viele wichtige Aspekte der Sprache kann man nicht durch Ausprobieren mit einer Implementation herausfinden, sondern nur durch Lesen der Sprachnorm. Selbst das Lesen von Lehrbüchern hilft nicht immer, da viele Lehrbücher wichtige Details der Sprache nicht vollständig oder nicht korrekt wiedergeben. Diese Eigenschaft teilt C  mit der auf C  aufbauenden Sprache C++.

Zum Vergleich: Verschiedene andere Programmiersprachen, wie beispielsweise Java  geben einen Wertebereich für den Datentyp »int« fest vor, den alle Implementationen genau übernehmen müssen. Solche konkreten Programmiersprachen sind leichter zu erlernen und zu beherrschen, aber weniger effizient als C.

Das undefinierte Verhalten eines int-Überlaufs

Wenn das Ergebnis einer Berechnung einen Wert ergibt, der in dem Datentyp des Ergebnisses nicht dargestellt werden kann, so ist das Verhalten der Berechnung undefiniert. Daher haben die folgenden Programme undefiniertes Verhalten. Das Protokoll der für dieses Skriptum verwendeten C -Implementation darf daher nicht  verallgemeinert werden! Es ist also durch die Sprachnorm nicht  garantiert, daß die Auswertung des Ausdrucks »INT_MIN - 1« wieder einen großen positiven Wert ergibt, vielmehr kann bei dieser Auswertung irgendetwas  passieren (wie auch bei einer Division durch Null).

main.c

#include <stdio.h> /* printf */
#include <limits.h> /* INT_MIN */

int main( void )
{ printf
( "%d\n", INT_MIN - 1 ); }

Protokoll
2147483647

Auch für die Auswertung von »INT_MAX + 1« ist nicht  garantiert, daß dies wieder einen sehr kleinen negativen Wert ergibt. Vielmehr ist auch hier das Verhalten undefiniert. Selbst, wenn man herausgefunden hat, daß eine Implementation dafür einen sehr kleinen negativen Wert ergibt, so hat man keine Garantie dafür, daß dies bei dieser Implementation immer so sein wird.

main.c

#include <stdio.h> /* printf */
#include <limits.h> /* INT_MIN */

int main( void )
{ printf
( "%d\n", INT_MAX + 1 ); }

Protokoll
-2147483648

Man sieht, daß eine Implementation bei undefiniertem Verhalten nicht immer eine Fehlermeldung  ausgibt. Trotzdem ist die Auswertung von »INT_MAX + 1« ein schwerer Fehler des Programmierers. Der Programmierer ist dafür verantwortlich, daß solche Auswertungen bei einem Ablauf seines Programmes niemals vorkommen. Das ist natürlich schwierig. Auch hier zeigt sich wieder, daß C  eine Programmiersprache ist, die schwer gut zu beherrschen ist. Es gibt andere Programmiersprachen, bei denen das Verhalten in solchen Fällen genau definiert ist, und die deswegen einfacher zu verwenden sind.

N2176 6.5 Expressions, Absatz 5 (Übersetzung und Original)
Tritt bei der Auswertung eines Ausdrucks eine Ausnahmesituation auf (d.h. ist das Ergebnis nicht mathematisch definiert oder nicht im Bereich der darstellbaren Werte für seinen Typ), ist das Verhalten undefiniert.
If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.

Übungsaufgaben

/   RAND_MAX

Der Ausdruck »RAND_MAX« hat den Typ »int« (wenn sich über ihm die Zeile »#include <stdlib.h>« findet).

Geben Sie den Wert des Namens »RAND_MAX« unter der von Ihnen verwendeten C -Implementation aus (unter Verwendung der Zeile »#include <limits.h>« am Anfang der Quelldatei).

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 stefanram722924 stefan_ram:722924 Wertnamen in C Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722924, slrprddef722924, 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/wertnamen_c