Global Vars, modulübergreifend - wie?



  • Hallo Forumsbesucher,

    voll peinlich, aber ich krieg' es einfach nicht mehr zusammen 😡 :
    Ich will von "foo.c" und "bar.c" aus die "variables.h" einbinden, um die dort definierten Variablen gemeinsam zu nutzen.

    Ich weiß, globals sind böse 👎 , aber bei meiner Sache würden sie sogar größeres Chaos verhindern helfen.

    Also, wenn jemand weiß wie das geht, bitte kurz darlegen!

    Dankeschön 😃



  • Geht das nicht mit extern?



  • pointercrash() schrieb:

    Ich will von "foo.c" und "bar.c" aus die "variables.h" einbinden, um die dort definierten Variablen gemeinsam zu nutzen.

    in einer .h sollteste besser keine variablen tun. machst du so:

    // foo.c
    int foobar;
    extern int barfoo;
    ..
    foobar = 1; // geht
    barfoo = 2; // geht
    
    // bar.c
    int barfoo;
    extern int foobar;
    ...
    foobar = 3; // geht auch
    barfoo = 4; // geht auch
    

    🙂



  • +fricky schrieb:

    in einer .h sollteste besser keine variablen tun. machst du so:

    // foo.c
    int foobar;
    extern int barfoo;
    ..
    foobar = 1; // geht
    barfoo = 2; // geht
    
    // bar.c
    int barfoo;
    extern int foobar;
    ...
    foobar = 3; // geht auch
    barfoo = 4; // geht auch
    

    🙂

    OK, das ^^^^^^ tut. Mein Problem bestand in einem "static", das macht wohl nicht nur Funktionen ausschließlich lokal, sondern auch Var- Symbole.

    Ganz happy bin ich aber immer noch nicht, die "extern blah", "extern blubb"- Geschichte ist ein Haufen Tipperei.

    Why so?
    Dann breite ich mal das ganze Problem aus: Eine Kiste startet mit harmlosen Defaults, die z.T. überladen werden sollen, wenn eine SD-Card drinsteckt, auf der ein passendes ini- File steht. Pro Maschinentyp sind es etwa 90 Parameter, für die sich eine zweistellige Anzahl Module z.T. überlappend interessiert. Im Sinne der Kapselung hat jedes Modul bisher das "ini" in der Init- Phase geöffnet und sich seinen Teil an Parametern rausgeholt.
    Was am PC kaum mehr als Zehntelsekunden dauert und - da nur einmalig - so keine Sau kratzt, bringt den Targetcontroller schon ins Schnaufen (16 mal öffnen, parsen, schließen).
    Neben reinen Performance- Erwägungen geht das noch so weiter, daß die Defaults/inis z.T. in weiterverarbeiteter Form an andere Module weitergereicht werden müssen, heißt, die Dinger justieren sich gegenseitig beim Initialisieren. Es ist nicht wirklich schön, in C die Werte von Modul zu Modul tragen zu müssen; wenn mal mehr als 6 Parameter übergeben werden müssen, ist auch der typedef nur noch Krücke. Deswegen die Idee, das irgendwo global zu deponieren.

    OK, wenn ich meinen Modulen schon die Kapselung nehmen muß, wär's halt schön gewesen, sie wenigstens nur an EIN File, bzw. EIN Modul binden zu müssen ... hat jemand dazu Ideen 😕



  • ^^mach dir für jeden konfigurationsblock eine struct und die packst du dann alle in eine grosse struct, so kannst du dann pointer darauf oder pointer auf die unterstrukturen überall herumreichen, z.b. um teilkomponenten zu initialisieren etc, die ganze struct oder teile davon von sd-karte laden, speichern usw.usw...
    🙂



  • Du kannst deine Variablen global in den C-Dateien definieren wie gewohnt, oder in einer einzigen, z.B. vars.c
    Dann kannste dir eine Headerdatei schreiben:

    extern int var1;
    extern type_x var_x;
    // .. etc
    

    So hast du alle 'externals' in einer Datei, du du dort inkludierst, wo sie gebraucht werden.
    Gruß,
    B.B.



  • +fricky schrieb:

    mach dir für jeden konfigurationsblock eine struct und die packst du dann alle in eine grosse struct ...

    Nee, war mir jetzt zu oversized, würde auch kein allzu tolles Runtimeverhalten abgeben ...
    Ich habe jetzt einfach Folgendes probiert:

    #include <stdio.h>
    #define MAIN
    #include <global.h>
    #undef MAIN
    #include <foo.h>
    
    int main(int argc, char *argv[])
    {
    	yumyum = 1;
    	foobar();
        printf("Hello, world! %d\n", yumyum);
        return 0;
    }
    

    Die global.h sieht so aus:

    #ifdef MAIN
    #define extern
    #endif
    extern int yumyum;
    #ifdef extern
    #undef extern
    #endif
    

    und die foo.c letztlich so:

    #include "foo.h"
    #include "global.h"
    
    void foobar(void)
    {
    	yumyum = 3;
    }
    

    Die Idee war letztlich, "extern" bei Erstdeklaration per Makro plattzumachen und bei allen weiteren Includes die Vars als extern einzubinden. Irgendwie haut das aber nicht hin, der Linker beharrt darauf, daß "multiple defines" vorliegen.
    Ich sitze jetzt schon mehr als zwei Minuten davor und sehe den Bock einfach nicht ...



  • pointercrash() schrieb:

    +fricky schrieb:

    mach dir für jeden konfigurationsblock eine struct und die packst du dann alle in eine grosse struct ...

    Nee, war mir jetzt zu oversized, würde auch kein allzu tolles Runtimeverhalten abgeben ...

    vom laufzeitverhalten wäre sowas schon ok.

    pointercrash() schrieb:

    #define extern
    ...
    #undef extern

    schlüsselwörter umzudefinieren o.ä. mögen manche compiler überhaupt nicht gern. wenn, dann mach dir wenigstens ein grosses EXTERN oder my_extern oder sowas in der art.
    🙂



  • pointercrash() schrieb:

    Die Idee war letztlich, "extern" bei Erstdeklaration per Makro plattzumachen und bei allen weiteren Includes die Vars als extern einzubinden. Irgendwie haut das aber nicht hin, der Linker beharrt darauf, daß "multiple defines" vorliegen.
    Ich sitze jetzt schon mehr als zwei Minuten davor und sehe den Bock einfach nicht ...

    Extern platt machen ist nicht nötig. Bin nicht sicher, geht glaub ich auch gar nicht, ist ja kein Macro.
    Was aber geht:

    // vars.h
    #ifndef VARS_H
    #define VARS_H
    
    extern int a;
    extern int b;
    
    #endif
    
    // a.c
    #include "vars.h"
    int a = 2;
    
    int modify_b()
    {
    	b = 2;
    }
    
    // b.c
    #include "vars.h"
    int b = 1;
    
    int modify_a()
    {
    	a = 1;
    }
    
    // main.c
    #include "vars.h"
    
    int main()
    {	
    	modify_a();
    	modify_b();
    	printf ("%d %d\n", a, b );
    	return 0;
    }
    

    Was mir gerade noch beim Joggen eingefallen ist: die Kapselung brauchst du deinen Modulen nicht zu nehmen. Exportiere einfach die Funktionen, welche deine statischen Variablen lesen/schreiben dürfen.



  • Big Brother schrieb:

    ... So hast du alle 'externals' in einer Datei, du du dort inkludierst, wo sie gebraucht werden.

    Sowas Ähnliches habe ich ja vor, nur daß ich ganz gerne alles in EINER Datei gesammelt hätte.

    Big Brother schrieb:

    ... die Kapselung brauchst du deinen Modulen nicht zu nehmen. Exportiere einfach die Funktionen, welche deine statischen Variablen lesen/schreiben dürfen.

    So hab' ich's ja derzeit mit den obig aufgeführten negativen Seiteneffekten. Da wäre als Alternative dann doch so 'ne struct/Pointergeschichte wie von +fricky vorgeschlagen, überlegenswert gewesen.

    Big Brother schrieb:

    schlüsselwörter umzudefinieren o.ä. mögen manche compiler überhaupt nicht gern. wenn, dann mach dir wenigstens ein grosses EXTERN oder my_extern oder sowas in der art.

    Genau das eben NICHT.

    #define extern
    

    erreicht ja genau, daß "extern" rein textuell durch nichts ersetzt, also gelöscht wird. Über den Define von MAIN kann ich steuern, ob die Vars angelegt werden oder als externe Referenzen in den Code gezogen werden sollen. Kein Compiler hat sich über den #define aufgeregt, aber unterschiedlich gemeckert wurde schon. Ich glaube wirklich, daß ein wesentliches Kriterium eines Compilers die Qualität seiner Fehlermeldungen sein sollte, nur einer hat mir den Hinweis auf einen richtig doofen Vertipper 😡 geliefert:
    main.c:

    #include <stdio.h>
    #define MAIN
    #include "global.h"    // NICHT <global.h>
    #undef MAIN
    #include "foo.h"       // MICHT <foo.h>
    // ...
    

    Jetzt geht's nämlich astrein ... 😃


Anmelden zum Antworten