Definition / Deklaration in Header file

Hi,

nachdem die 1.6.7 etwas saubereren Programmierstil von mir abverlangt, bin ich aktuell mit globalen Variablen beschäftigt.
Ich habe das hier gelesen:

// file.h
extern int x; // declaration

// file.c
#include "file.h"
int x = 1; // definition and re-declaration

So gemacht funktionert es ja auch.

Allerdings stellt sich mir gerade die Frage, ob man die Definition der Variable nicht auch im Header (file.h) durchführen kann?
Hätte aus meiner Sicht den Charme, dass ich die Definition aller globalen Variablen an einer Stelle und nicht über mehrere cpps verstreut hätte.

hk007:
...

IMO spricht nichts dagegen, Variablen gleich bei der Deklaration zu initialisieren. Blöd könnte sein, dass man den Wert nicht mal eben nachgucken kann, wenn man in file.c arbeitet. Hierzu muss man dann halt file.h laden.

Gruß

Gregor

Ich bins halt so aus der Steuerungstechnik gewohnt. Da gibts ne Variablentabelle. Und die ist eh immer nebenbei offen zum "Nachschauen"

Also dann so??

// file.h#ifndef My_Header
#define My_Header

extern int x;  // declaration
int x = 1;    // definition and re-declaration
extern bool HundKatzeMaus;
bool HundKatzeMaus;

#endif

Mit "initialisieren" meinst du die Wertzuweisung? Die sehe ich aber nur als optional.

Nö,

so klappts nicht.
Da bekomm ich "multiple definition..."

Wie geht das dann?

Wenn du Variablen im Header definierst enthält jede Datei die den Header inkludiert eine eigene Version davon. Das kann bei kleinen Projekten ok sein, aber auch sehr problematisch werden.

Das möchte ich natürlich auch nicht.

Also nur der Weg wie in Post#1 angedeutet?
Im Header deklarieren und in der cpp definieren. Anders gehts nicht?

hk007:
… Anders gehts nicht?

Pardon, ich habe vorhin Mist erzählt.

Schon die Variante im ersten Posting dürfte nicht funktionieren. Mit „extern int x“ teilst Du dem Compiler mit, dass es diese Variable gibt (und dass sie vom Typ int ist), aber anderswo (extern eben) deklariert wurde. Wenn Du dann im gleichen „scope“ (Sichtbarkeitsbereich) erneut eine Variable mit diesem Namen deklarierst, meckert der Compiler.

Ich deklariere Variablen meistens dort, wo ich sie benötige – und dort werden sie üblicherweise gleich mit einem passenden Wert initialisiert. Die Namen wähle ich möglichst so, dass sofort klar ist, worum es geht. Und weil solche Deklarationen im Code passieren, tauchen Deklarationen in meinen Header-Dateien nur selten auf.

Gruß

Gregor

Hmmm...

Aber die Variante im ersten Posting funzt.
Und ist (aus der Sicht meiner bescheidenen Programmierkenntnisse) die einzige, um eine Variable für andere cpp's nutzbar zu machen.

Es stellt sich die Frage, in wiefern diese Variable überhaupt in anderen Files zur Verfügung gestellt werden soll. Das deklarieren innerhalb einer C-Datei hat den "Vorteil", dass sie nicht nach aussen hin bekannt ist. Ich nutze meist eine Funktion mit einem direkten Rückgabewert.

Kleines Beispiel:

Ich lese in einem File über DS18B20 eine Temperatur ein.
In einem anderen File gebe ich den Wert über Ethernet aus.
Dazu habe ich dann noch ein LCD, auf dem ich die Temperatur anzeige.

Für jede dieser Einheiten habe ich eine eigene Datei (.cpp/.ino), damit das ganze für mich etwas übersichtlicher ist.

hk007:
Hmmm...
Aber die Variante im ersten Posting funzt.

Ja, tut sie. Und ich kapiere nicht, warum. Entweder finde ich heraus, wo meine Denke nicht stimmt, oder ich muss ohne Antwort weiterleben.

Das Leben ist hart, nech :slight_smile:

Gregor

Aber das Beste kommt noch:

Ich dachte mit ner sauberen Definition im HeaderFile wär ich mit vorne dabei.

Jetzt wollte ich das Projekt wieder mit der 1.6.5 kompilieren, dann geht das nicht mehr.
Da findet er die Bilbliotheken nicht, wenn sie im Header included sind, und das Header mit include in der cpp steht.
Jetzt habe ich die libs sowohl im Header. als auch in der Haupt-ino stehen. Dann kann ich zwischen den Versionen springen.

Also entweder habe ich noch nicht das richtige (C/C++ konforme) entdeckt, oder die Arduino-IDEs halten sich nicht an die Regeln.

Zu deiner Frage:
Ja, es geht. Wobei man das include in meinem Beispiel in der cpp, wo man die int definiert eigentlich nicht braucht. Diese cpp weiss ja von der Variable. Aber in den anderen, muss es stehen, wenn man die Variable verwenden will.

Jetzt wollte ich das Projekt wieder mit der 1.6.5 kompilieren, dann geht das nicht mehr.
Da findet er die Bilbliotheken nicht, wenn sie im Header included sind, und das Header mit include in der cpp steht.
Jetzt habe ich die libs sowohl im Header. als auch in der Haupt-ino stehen. Dann kann ich zwischen den Versionen springen.

Ja, das ist notwendig!

Arduino 1.6.5 untersucht die Ino Datei nach includes.
*.h und *.cpp Dateien werden nicht analysiert.

Es ist also unumgänglich z.B. Wire.h in der INO Datei und in der betreffenden .h/.cpp einzubinden.

Aber die Variante im ersten Posting funzt.
Und ist (aus der Sicht meiner bescheidenen Programmierkenntnisse) die einzige, um eine Variable für andere cpp's nutzbar zu machen.

Ja, so ist es.
Das ist der bewährte Weg. Seit über 35 Jahren, als der richtige anerkannt.
Wobei... wenn es möglich ist, auf globale Daten zu verzichten, dann sollte man das auch tun.

Und was ist für die Zukunft der bessere Weg?
Lauter kleine inos basteln dann sicherlich nicht.
Nachdem Arduino-IDE jetzt den Build-Prozess umgestellt hat, ist es wohl besser mit *cpp/*h zu arbeiten, selbst wenn man aktuell noch die 1.6.5 nutzt. Oder?
Die Main.ino sollte wohl eine *.ino bleiben.

Arduino 1.6.5 untersucht die Ino Datei nach includes.
*.h und *.cpp Dateien werden nicht analysiert.

Gibts da irgendwo noch mehr Detailinfos? Evtl. auch, was bei 1.6.5 → 1.6.6(1.6.7) beim Buildprozess umgestellt wurde? Dann würde ich das besser verstehen und gezielter “reagieren” können.

Nachdem Arduino-IDE jetzt den Build-Prozess umgestellt hat, ist es wohl besser mit *cpp/*h zu arbeiten, selbst wenn man aktuell noch die 1.6.5 nutzt.

Auch vorher schon, wäre es der bessere Weg gewesen.
Denn das ist kompatible mit dem Rest der C/C++ Welt.
Also 1:1 in anderen Entwicklungsumgebungen nutzbar.

Das mit den vielen ino Dateien war von Anfang an ein Irrweg.

Die Main.ino sollte wohl eine *.ino bleiben.

Wird sich in naher Zukunft nicht ändern lassen.....

Gibts da irgendwo noch mehr Detailinfos?

Da sich das scheinbar dauernd ändert, und ich sowieso gar keine Lust habe mich mit den Innereien rum zu schlagen, folgenden Tipp von mir: google(arduino build process)