Konstanten mit Dateigültigkeitsbereich in C
Konstante Felder
Eine Quelldatei kann neben den Funktionsdefinitionen auch Konstantendefinition enthalten. Damit kann beispielsweise ein Modul mit mathematischen Konstanten realisiert werden.
tut/math/value.h#ifndef tut_math_value_h_INCLUDED_20030320
#define tut_math_value_h_INCLUDED_20030320
/** @file value.h
@brief Einige mathematische Werte. */
/// Die Kreiszahl pi
extern double const pi;
/// Die Eulersche Zahl e
extern double const e;
#endiftut/math/value.c#include "value.h"
double const pi = 3.1415926535897932384626433832795028841972;
double const e = 2.7182818284590452353602874713526624977572;value_ec.c/** @file value_ec.c
@brief Bespielklient (ec = example client) fuer die Klasse "value". */
#include <stdio.h> // printf
#include "tut/math/value.h" // pi
int main()
{ printf( "Der Umfang eines Kreises mit dem Radius 9.8 ist %.2f.\n", 2 * pi * 9.8 ); }stdoutDer Umfang eines Kreises mit dem Radius 9.8 ist 61.58.
Die Kopfdatei "value.h" enthält die „Schnittstelle“ des Moduls: Es handelt sich um zwei reine Deklarationen. Daß diese Deklarationen keine Definitionen sind, wird durch das einleitende Schlüsselwort "extern" festgelegt. Diese Deklarationen legen also nur den Typ ihrer Bezeichner fest.
Die Implementationsdatei "value.c" enthält die Definition der beiden Konstanten. Durch die Initialisierung, also die Angabe eines Anfangswertes wird klargestellt, daß es sich um Definitionen handelt.
Neben den reinen Deklarationen mit dem Speicherklassen-Spezifizierer "extern" und den Definition mit einem Anfangswert gibt es noch eine Zwischenform, bei der weder der Speicherklassen-Spezifizierer "extern" noch ein Anfangswert verwendet wird, etwa wie in "double const pi;", diese sogenannte vorläufige Definition ist unnötig kompliziert und sollte vermieden werden.
Man sagt, daß der hier definierte Bezeichner "pi" und der Bezeichner "e" Dateigültigkeitsbereich haben. Das heißt, daß sie potentiell in ihrer gesamten Quelldatei sichtbar sind, davon wird hier aber kein Gebrauch gemacht.
Außerdem haben diese beiden Bezeichner externe Bindung. Das bedeutet, daß die Bezeichner in anderen Quelldatei verwendet werden können. Die Bezeichner werden dann an die Entitäten gebunden, an der sie auch in der Quelldatei gebunden wurden, die ihre Definition enthält, wenn die Kompilate miteinander verbunden werden. Davon wird bei der Verwendung des Bezeichners "pi" in der Quelldatei "value_ec.c" Gebrauch gemacht. Dieser wird an den Wert gebunden, an den auch der Bezeichner "pi" in der Quelldatei "value.c" gebunden wurde.
Private Sichtbarkeit
Wenn eine Konstanten mit Dateigültigkeitsbereich nur von Funktionen ihrer Quelldatei verwendet werden soll, dann sollte sie nur intern (d.h. innerhalb ihrer Quelldatei) verbunden werden. Solch eine interne Bindung wird durch den Speicherklassen-Spezifizierer "static" festgelegt.
Das Modul "tut/phys/value" veröffentlicht über seine Schnittstelle aus zwei Funktionen den Zahlenwert der Lichtgeschwindigkeit in Meter pro Sekunde bzw. in Kilometer pro Stunde. Um die für die Berechnung nötigen Werte nicht in den beiden Funktionsdefinitionen wiederholen zu müssen, werden Konstanten mit den benötigten Werten in der Implementation definiert. Diese Konstanten sollen aber nicht nach außen sichtbar werden, damit sie bei Bedarf jederzeit verändert werden können, ohne daß dies die Klienten stört. Daher werden die Konstanten als Konstanten mit interner Bindung gekennzeichnet.
tut/phys/value.h#ifndef tut_phys_value_h_INCLUDED_20030311
#define tut_phys_value_h_INCLUDED_20030311
/** @file value.h
@brief Einige physikalische Werte. */
/// c in m/s
extern double c_ms();
/// c in km/h
extern double c_kmh();
#endiftut/phys/value.c#include "value.h" // c_ms, c_kmh
static double const m = 1.;
static double const s = 1.;
static double const km = 1000.;
static double const h = 60. * 60.;
static double const c = 299792458.;
double c_ms() { return c /( m/ s ); }
double c_kmh() { return c /( km/ h ); }pvalue_ec.c/** @file pvalue_ec.c
@brief Bespielklient (ec = example client) fuer das Modul "tut/phys/value". */
#include <stdio.h> // printf
#include <locale.h> // LC_ALL, setlocale
#include "tut/phys/value.h" // c_ms, c_kmh
int main()
{ setlocale( LC_ALL, "" );
printf( "Die Lichtgeschwindigkeit betraegt %.2f m/s oder oder %.2f km/h.\n",
c_ms(), c_kmh() ); }::std::coutDie Lichtgeschwindigkeit betraegt 299792458,00 m/s oder oder 1079252848,80 km/h.
Es ist von der Funktion "main" aus nun nicht möglich, auf die Modulkonstanten mit interner Bindung, wie beispielsweise die Konstante "c", zuzugreifen, nur die beiden öffentlichen Modulfunktionen mit externer Bindung können aufgerufen werden.
Eine „Konstante“, wie sie hier vorgestellt wurde, gilt in C allerdings nicht als konstant: Sie kann nicht in Ausdrücken verwendet werden, die einen konstanten Wert haben müssen. Daher kann beispielsweise in der Quelldatei "tut/phys/value.c" die Konstante "km" nicht mit dem Ausdruck "1000. * m" („1000 Meter“) initialisiert werden, nur der Ausdruck "1000." kann hier zum Initialisieren verwendet werden. Insofern sind die hier als „Konstanten“ vorgestellten Entitäten nicht in jeder Hinsicht Konstanten: Sie können in Ausdrücken nur dann wie Konstanten verwendet werden, wenn kein „konstanter Ausdruck“ erwartet wird.