Unterschied Präprozessor Konstante und normale Konstante



  • Hallo zusammen,
    ich bin gerade dabei von Java auf C umzusteigen... Ich habe eine Frage zu konstanten...
    Mal ein einfaches Beispiel: Angenommen ich hab ein Programm in dem immer wieder der gleiche Wert vorkommt. Sagen wir z. B. der Wert 9.81 ...
    Nun kann ich ja eine globale Konstante definieren (const double g = 0.81) oder ich kann sagen #define g 9.81 ...
    Es funktioniert ja beides, aber vllt. kann mir jemand sagen was der Unterschied ist und was besser ist. Danke.



  • Wenn du mit #define eine Konstante definierst bedeutet dass, das der Präprozessor vor dem Kompilieren alle Vorkommen der Konstante "g" durch den Wert "9.81" ersetzt. Wenn du es mit "const double" machst wird der Wert der Konstante in den Speicher geschrieben und zur Laufzeit ausgelesen.
    Normalerweise ist von der Variante mit der symbolischen Konstante eher abzuraten weil z.B. Typsicherheit nicht existiert.



  • Mithilfe des static-Keywords kannst du einer Konstanten auch noch 'internal linkage' verpassen, was ihren Scope effektiv auf die jeweilige Übersetzungseinheit limitiert. Dies erlaubt dem Compiler den Speicherplatz für die Konstante komplett zu eliminieren und den Wert stattdessen direkt in die Befehle einzutragen. Zumindest der GCC macht davon auch Gebrauch, wenn sinnvoll.

    Außerdem ersparst du dir so eventuell Probleme mit doppelten Definitionen bei Allerweltsnamen wie 'g'. 😉


  • Mod

    DarkShadow44 schrieb:

    Wenn du mit #define eine Konstante definierst bedeutet dass, das der Präprozessor vor dem Kompilieren alle Vorkommen der Konstante "g" durch den Wert "9.81" ersetzt. Wenn du es mit "const double" machst wird der Wert der Konstante in den Speicher geschrieben und zur Laufzeit ausgelesen.
    Normalerweise ist von der Variante mit der symbolischen Konstante eher abzuraten weil z.B. Typsicherheit nicht existiert.

    So wirklich aktuell ist dieser Tipp übrigens nicht mehr. Das gilt eventuell bei der Verwendung der Konstanten über mehrere Übersetzungseinheiten*, aber ein moderner (d.h. jünger als 20 Jahre) Compiler kann selbst bei nicht-const Variablen die Werte zur Compilezeit auflösen, wenn er beweisen kann, dass diese sich nicht ändern (und bei const-Variablen ist es trivial).

    Wichtiger ist, dass const-Variablen nicht als Compilezeitkonstanten im strengen Sinne der Sprache gelten:

    #define SIZE 5
    const int size = 5;
    
    int main()
    {
     int foo[SIZE];  // Erlaubt
     int bar[size];  // Nicht erlaubt, bzw. VLA in C99
    }
    

    *: Wirklich moderne Compiler (d.h. jünger als ca. 5 Jahre) können das auch über Übersetzungseinheiten hinweg optimieren.



  • Es gibt ja da noch den Datentyp enum:

    enum nameDim { name_maxlen = 16 }; // ganzzahlige Konstante
    
    int main ( void )
    {
    	char name [ name_maxlen ] = {0}; // erlaubt
    	return 0;
    }
    

Log in to reply