Konstanten für verschiedene Sourcefiles in einem Headerfile deklarieren



  • Hallo NG,

    ich habe in diesem Beispiel zwei Sourcefiles und ein Headerfile. Im Headerfile deklariere ich eine Konstante, die in beiden Sourcefiles benötigt wird. Die Sourcefiles ergeben am Ende ein Target. Beim Linken führt das dann aber verständlicherweise zu folgendem Fehler.

    multiple definition of `max_entries'

    Das Beispiel ist wild zusammengestöpselt. Es geht also nicht darum was mit "max_entries" gemacht wird, sondern einzig und allein darum "max_entries" allen Sourcefiles zugänglich zu machen.

    Das Headerfile:

    #ifndef MAXVALUES_H
    #define MAXVALUES_H
    
    const int max_entries = 65536;
    
    #endif
    

    #include "maxvalues.h"

    Das erste Sourcefile

    #include <stdlib.h>
    #include "maxvalues.h"
    
    int *p_buffer = NULL;
    
    bool create_items {
      bool retval = false;
      p_buffer = calloc( max_entries, sizeof( char ) );
    
      if ( NULL != p_buffer ) {
        retval = true;
      }
    
      return retval;
    }
    
    void remove_items {
      if ( NULL != p_buffer ) {
        free(p_buffer);
        p_buffer = NULL;
      }
    }
    

    Das zweite Sourcefile

    #include "maxvalues.h"
    
    void init_list (int *array) {
      int index = 0;
    
      for ( index = 0; index < max_entries; index++ ) {
        array[index] = 4711;
      }
    }
    

    Ich benötige diesen (und einige andere Werte auch) in recht vielen Sourcefiles. Deshalb möchte ich nicht die Konstante in jedem Sourcefile mit anderem Namen deklarieren. Und Macros möchte ich aus gründen der Typsicherheit auch nicht benutzen. Zumal ein Macro zum Warning "multiple definition of max_entries" führen müsste.

    Grüße und Danke schonmal,
    BlackPepper



  • Deklarier´ die Konstante in der Header Datei mit "extern" und definier´ sie in einer .cpp Datei.



  • Hallo DocShoe,

    aber dann kann ja in "max_entries" in jedem Sourcefile einen anderen Wert haben. Externe Variablen werden ja nicht initialisiert. Und wenn sich der Wert ändert, muß ich ja auch in jedem Sourcefile eine Änderung machen. Und ich hab Deinen Tipp gerade ausprobiert. Beim linken trat der gleiche Fehler auf, weil wieder in jedem Sourcefile die gleiche Variable declariert wurde.

    Gruß,
    BlackPepper



  • DocShoe schrieb:

    Deklarier´ die Konstante in der Header Datei mit "extern" und definier´ sie in einer .cpp Datei.



  • Hallo Fellhuhn,

    der Sourcecode sieht nun folgendermaßen aus:
    Das Headerfile:

    #ifndef MAXVALUES_H
    #define MAXVALUES_H
    
    extern const int max_entries;
    
    #endif
    

    #include "maxvalues.h"

    Das erste Sourcefile

    #include <stdlib.h>
    #include "maxvalues.h"
    
    const int max_entries = 65536;
    
    int *p_buffer = NULL;
    
    bool create_items {
      bool retval = false;
      p_buffer = calloc( max_entries, sizeof( char ) );
    
      if ( NULL != p_buffer ) {
        retval = true;
      }
    
      return retval;
    }
    
    void remove_items {
      if ( NULL != p_buffer ) {
        free(p_buffer);
        p_buffer = NULL;
      }
    }
    

    Das zweite Sourcefile

    #include "maxvalues.h"
    
    const int max_entries = 65536;
    
    void init_list (int *array) {
      int index = 0;
    
      for ( index = 0; index < max_entries; index++ ) {
        array[index] = 4711;
      }
    }
    

    Ich denke das war damit gemeint. Sourcefile eins und zwei lassen sich ja auch kompilieren. Die .o Datei ist da. Aber wenn der Linker alle .o Dateien zusammenlinken will, meint er immer noch:

    multiple definition of `max_entries'

    Gruß,
    BlackPepper



  • Fellhuhn schrieb:

    DocShoe schrieb:

    Deklarier´ die Konstante in der Header Datei mit "extern" und definier´ sie in einer .cpp Datei.



  • Hallo Fellhuhn,

    Aaaa!!! Danke.

    Gruß,
    BlackPepper



  • 😉



  • Eins sei die Zahl der .cpp Dateien, in der du die Konstante definierst. Auf keinen Fall sei die Zahl 2. Die drei scheidet von vorneherein aus.



  • BlackPepper schrieb:

    ich habe in diesem Beispiel zwei Sourcefiles und ein Headerfile. Im Headerfile deklariere ich eine Konstante, die in beiden Sourcefiles benötigt wird.

    Deklarierst Du sie oder definierst Du sie? Das ist ein Unterschied.

    BlackPepper schrieb:

    Die Sourcefiles ergeben am Ende ein Target. Beim Linken führt das dann aber verständlicherweise zu folgendem Fehler.

    multiple definition of `max_entries'

    Aha. Man achte auf das zweite Wort: "definition".

    BlackPepper schrieb:

    Das Beispiel ist wild zusammengestöpselt. Es geht also nicht darum was mit "max_entries" gemacht wird, sondern einzig und allein darum "max_entries" allen Sourcefiles zugänglich zu machen.

    Das Headerfile:

    #ifndef MAXVALUES_H
    #define MAXVALUES_H
    
    const int max_entries = 65536;
    
    #endif
    

    Wenn das wirklich so in deinem Header drin steht, darf der Linker Dir diese Fehlermeldung nicht ausgeben. Irgendwas stimmt hier nicht. Kann es sein, dass Du das const nur hier im Beitrag stehen hast, nicht aber in Deinem Quellcode?

    BlackPepper schrieb:

    Das erste Sourcefile

    #include <stdlib.h>
    #include "maxvalues.h"
    
    ...
    

    Das zweite Sourcefile

    #include "maxvalues.h"
    
    ...
    

    Sollte klappen. Zumindest das mit dem max_entries-Dingen. Denn Du definierst es im Header mit const, wodurch implizit eine interne Bindung erzwungen wird. Du hast also sozusagen zwei Konstanten. Ein max_entries für die Übersetzungseinheit "erstes Sourcefile" und ein max_entries" für die ÜE "zweites Sourcefile". Die beiden sind verschieden (da interne Bindung). Der Linker darf sich hier nicht beschweren.

    BlackPepper schrieb:

    Ich benötige diesen (und einige andere Werte auch) in recht vielen Sourcefiles.

    Du kannst sie ruhig so in die Header-Dateien packen. Hauptsache es steht ein "const" dabei; denn ohne const hätten die Objekte eine externe Bindung, was dann zu Deiner Fehlermeldung führt.



  • ...zumindest impliziert const auf der globalen bzw Namensraum-Ebene bei C++ "interne Bindung". Es kann auch sein, dass Du einen C-Compiler drauf angesetzt hast, der const anders handhabt. Da müsstest Du Dich schon entscheiden. Willst Du C-kompatibel bleiben musst Du entweder noch ein "static" einbauen:

    static const int foo = 42;
    

    oder benutzt einfach

    #define FOO 42
    

    Letzteres ist unter C üblicher, weil der C Compiler im ersten Fall foo nicht als Compile-Zeit-Konstante ansieht und dementsprechend auch nicht in Kontexten eingesetzt werden kann, wo eine Compile-Zeit-Konstante benötigt wird.


Anmelden zum Antworten