Hi. Ich habe ein paar kleine Routinen in C für meinen uC geschrieben. Es funktioniert soweit auch alles, aber meine main.c wird langsam etwas zu lang. Ich würde gerne ein paar Funktionen in externe c.files auslagern. Gibt es eine Möglichkeit, dass die externen c.files die globalen Variablen aus dem main kennnen, oder muss man dass immer alles einzeln übergeben?
klaro, in main.c: int globaleVariable1; in nem andern quellfile: extern int globaleVariable1; //variablenname muss genau dem //im main.c ensprechen
Besser ist es, für so etwas eine Headerdatei zu verwenden und diese in die entsprechenden Module einzubinden. Auch sollten, der Struktur halber, die globalen Variablen nicht im Hauptmodul, sondern in einem eigenen Modul definiert werden. Beispiel: --- global.h // Deklaration extern int globaleVariable1; extern int globaleVariable2; --- global.c #include "global.h" // Definition int globaleVariable1; int globaleVariable2; --- main.c #include "global.h" ... etc. globaleVariable1 = 0; --- krempel.c #include "global.h" ... etc. globaleVariable1 = 0; Um Tippfehler auszuschließen, kann man auch so vorgehen: --- global.h #ifdef IMPLEMENTIERUNG // Definition #define bla #else // Deklaration #define bla extern #endif bla globaleVariable1; bla globaleVariable2: --- global.c #define IMPLEMENTIERUNG #include "global.h" // und nichts weiter --- main.c #include "global.h" (wie gehabt) ... etc. globaleVariable1 = 0; So müssen globale Variablen ausschließlich einmal in einer Headerdatei aufgelistet werden und deren Definition und Deklaration erfolgt durch die gleiche Headerdatei. Das Makro IMPLEMENTIERUNG darf nur exakt einmal beim Einbinden der Headerdatei definiert sein (das sorgt dafür, daß dann das Schlüsselwort "extern" entfällt). Es gibt C-Compiler, die einem das Leben einfacher machen, in dem sie (genauer: deren Linker) Symbole gleichen Namens zusammenfasst (da genügt es, in jedem Modul die globalen Variablen mit gleichem Namen zu definieren), aber das ist nicht portierbar und dürfte auch (tipp)-fehleranfällig sein.
@Rufus In jedem Fall drucke ich mir das mal für spätere Verwednung auf aber im Moment komme ich wohl mit Svens Version besser zurecht. Trotzdem Danke
> Das Makro IMPLEMENTIERUNG darf nur exakt einmal beim > Einbinden der Headerdatei definiert sein a) <mode="haarspalter">das ist kein Makro, sondern ein Präprozessorsymbol (ein Makro hat Parameter) </mode> b) nach dem Standard dürfen globale Symbole niemals mit einem Unterstrich beginnen, wenn du nicht gerade an der libc programmierst. Darunter fallen insbesondere auch Präprozessorsymbole, auch wenn das gerne falsch gemacht wird. Richtig wäre also "#define IMPLEMENTIERUNG" (Unterstriche am Ende des Bezeichners sind aber erlaubt). Normalerweise sorgt die GROSS-Schreibung schon dafür, dass eine keine Namenskollisionen gibt.
Chris: Schöne Haarspalterei. Was machst Du jetzt mit den gespaltenen Haaren? Zusammenknoten? Zum Punkt b) Sieh Dir mal die ganzen #defines in etlichen Sourcen (MFC, wxWidgets, was weiß ich wo) an - da wird ein führender Unterstrich äußerst gerne verwendet. Auch ist die Abfolge #ifndef _INC_STDIO #define _INC_STDIO ... viele Zeilen #endif /* _INC_STDIO */ äußerst beliebt, um Mehrfacheinbindungen auszuschließen. (Zitat aus stdio.h, enthalten im Lieferumfang von MSVC6) Das scheint auch nicht MS-spezifisch zu sein: #ifndef __stdio_h #define __stdio_h ... viele Zeilen #endif (hier: stdio.h von Rowley Crossworks for ARM) Welchen Standard meinst Du mit "dem Standard"?
stdio.h ist auch Teil der ,Implementierung', die dürfen das. Wenn wxWidgets das auch macht, riskieren sie u. U. eine Kollission mit Compiler und/oder Bibliothek. Als Anwender gilt uneingerschränkt: definiere nie selbst irgendwelche Namen, die mit einem Unterstrich anfangen. (Ob du derartige Namen, die die Implementierung benutzt, auch benutzen darfst, d.h. ob sie ein exportiertes Interface darstellen, erzählt die die jeweilige Doku.) Header `idempotency' kann man für seine Applikations-Header auch ohne den Unterstrich locker erreichen: #ifdef MYAPP_H #define MYAPP_H ... #endif /* MYAPP_H */ Ob das Zeug woanders gerne verwendet wird oder nicht, spielt keine Geige, es bleibt falsch. Besonders deutsche Autofahrer fahren auch gern mal schneller, als die Polizei erlaubt -- und riskieren dafür genauso eine entsprechende Quittung wie C-Programmierer, die sich nicht an die Regeln halten.
@Joerg: Ich wollte hier keinerlei Diskussion lostreten. Daher mein Beispiel von neulich in "korrigierter" Fassung: #ifdef IMPLEMENTIERUNG // Definition #define VIELLEICHT_EXTERN #else // Deklaration #define VIELLEICHT_EXTERN extern #endif VIELLEICHT_EXTERN globaleVariable1; VIELLEICHT_EXTERN globaleVariable2: --- global.c #define IMPLEMENTIERUNG #include "global.h" // und nichts weiter --- main.c #include "global.h" (wie gehabt) ... etc. globaleVariable1 = 0; Zufrieden?
Ja. :-) Rufus, das Problem ist, dass du aufgrund deiner guten Beiträge natürlich ringsum ganz schnell ,,Guru-Status'' erhälst und damit für andere zum Vorbild wirst... Da sollte man sich dann einfach Mühe geben, auch auf derartige Kleinigkeiten zu achten.
Wenn ich das richtig interpretiere gibt es also Funtionen, die über das "Standart - C" hinausgehen, (sagen wir mal um die Arbeit zu vereinfachen) die dann alle mit einem oder 2 Unterstrichen anfangen, damit sie nicht genauso heißen, wie zB eine vom Programmierer geschriebene Funktion Makro Variable ... was auch immer??
So ungefähr. Der Standard schreibt genau vor, welche Funktionen und Makros definiert werden, wenn man eine bestimmte Header-Datei (z. B. <stdio.h>) hereinzieht. Es ist vorgeschrieben, was danach deklariert bzw. definiert sein muss, und was als mögliche Erweiterung sein darf. (Z. B. reserviert <string.h> alle Funktionsnamen, die mit "str" beginnen.) Wenn eine Implementierung jetzt für irgendwas zusätzliche internen Namen benötigt, muss sie diese zur Vermeidung von Kollisionen aus dem Namensraum belegen, der für die Implementierung vorbehalten ist. Benötigt beispielsweise ein <stdio.h> zur Implementierung von "FILE *" eine struct, deren Name im Headerfile für die Applikation sichtbar wird, dann darf sie nicht "struct file" nehmen (weil das mit der Applikation kollidieren kann), sondern muss "struct _file" nehmen. Der Unterschied zwischen einem und zwei Unterstrichen ist aus Benutzersicht marginal und kann hier vernachlässigt werden.
eine fehlt noch ... Ich habe ein "volatile static char", dass mir sozusagen als Escape-Taste dient. Die bekomme ich einfach nicht hin bei der Auslagerung. Gibt es da noch was zu beachten?
"static" bedeutet, daß das Symbol nicht auf Linkerebene sichtbar ist. Somit kann Code aus einem Modul nicht auf eine in einem anderen Modul als static definierte Variable zugreifen, ebensowenig, wie Code aus einem Modul nicht auf als static deklarierten Code in einem anderen Modul zugreifen kann. Dir dürfte damit geholfen sein, wenn Du das "static" entfernst.
klappt super. Ich muss wohl noch ein bisschen an meiner Programmstrukturierung arbeiten.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.