Forum: Compiler & IDEs anfaengerfrage


von cerberus (Gast)


Lesenswert?

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?

von Sven Bohner (Gast)


Lesenswert?

klaro,

in main.c:

int globaleVariable1;


in nem andern quellfile:

extern int globaleVariable1; //variablenname muss genau dem
      //im main.c ensprechen

von Rufus T. Firefly (Gast)


Lesenswert?

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.

von cerberus (Gast)


Lesenswert?

Ah ha! Cool. Danke

von cerberus (Gast)


Lesenswert?

@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

von Chris (Gast)


Lesenswert?

> 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.

von Rufus T. Firefly (Gast)


Lesenswert?

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"?

von Jörg Wunsch (Gast)


Lesenswert?

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.

von Rufus T. Firefly (Gast)


Lesenswert?

@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?

von Jörg Wunsch (Gast)


Lesenswert?

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.

von cerberus (Gast)


Lesenswert?

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??

von Jörg Wunsch (Gast)


Lesenswert?

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.

von cerberus (Gast)


Lesenswert?

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?

von Rufus T. Firefly (Gast)


Lesenswert?

"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.

von cerberus (Gast)


Lesenswert?

Na das werde ich doch gleich mal ausprobieren. Danke

von cerberus (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.