Forum: Compiler & IDEs #define in main.c und #ifndef in include-Datei ergibt redefinition-error


von Stefan S. (stefanst)


Lesenswert?

Guten Tag!

Ich habe ein C-Projekt, bestehend aus main.c und uart.h bzw der 
entsprechenden c-Datei. Nun habe ich folgendes Konstrukt:

In uart.h steht unter anderem folgendes:
[c]
/** Size of the circular receive buffer, must be power of 2 */
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif
/** Size of the circular transmit buffer, must be power of 2 */
#ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32
#endif
[\c]

Und in meiner main.c:
[c]
#define UART_RX_BUFFER_SIZE 64 // Size of the circular receive buffer, 
must be power of 2
#define UART_TX_BUFFER_SIZE 64 // Size of the circular transmit buffer, 
must be power of 2
[\c]

Eigentlich möchte ich die uart.h unberührt lassen und besagtes define in 
main.c auslagern. Leider kommt dabei ein redefinition-error, wenn ich 
#include "uart.h" vor dem define im main-file setze. Einzige Möglichkeit 
die ich bisher sehe ist das include unter das define zu setzen, was aber 
doch irgendwie unschön ist... so ein include gehört doch als erstes in 
main.c... Irgendeine Idee, das zu bewerkstelligen?

EDIT: Irgendwie krieg ich das mit dem [c]...[\c] formatieren nicht 
hin...

Viele Grüße,
Stefan

von Frank L. (franklink)


Lesenswert?

Hallo,
genauso wie Du es machst, ist es die einzige Möglichkeit. Ein 
redefinieren der defines geht in diesem fall nur so.

Vorausgesetzt, Du willst die uart.h nicht verändern. Ich stelle mir nur 
die Frage, warum willst Du die uart.h nicht verändern?

Gruß
Frank

[edit] Alternativ, kannst Du ein #undef verwenden.
Nach dem #include "uart.h"
machst Du ein #undef auf die beiden defines und deklarierst Deine 
eigenen. Das funktioniert aber nur, wenn auf die beiden defines nicht 
innerhalb der uart.h zugegriffen wird.

von Klaus W. (mfgkw)


Lesenswert?

Stefan S. schrieb:
> EDIT: Irgendwie krieg ich das mit dem [c]...[\c] formatieren nicht
> hin...

/c statt \c nehmen?

von Stefan E. (sternst)


Lesenswert?

Stefan S. schrieb:
> Einzige Möglichkeit
> die ich bisher sehe ist das include unter das define zu setzen, was aber
> doch irgendwie unschön ist...

Ich sehe nicht, was daran "unschön" sein soll, insbesondere wenn man es 
entsprechend zusammenfasst, so dass der Zusammenhang offensichtlich 
wird:
1
#include "blah.h"
2
3
#define UART_RX_BUFFER_SIZE 64
4
#define UART_TX_BUFFER_SIZE 64
5
#include "uart.h"

von Klaus W. (mfgkw)


Lesenswert?

Frank Link schrieb:
> Vorausgesetzt, Du willst die uart.h nicht verändern. Ich stelle mir nur
> die Frage, warum willst Du die uart.h nicht verändern?

Weil eine Headerdatei nicht dazu da ist, ständig editiert zu werden?
Da gehören Sachen rein, die einfach nur verwendet werden.
Sonst könnte man ihren Inhalt auch gleich in die .c reinmatschen.

Daß es hier oft anders gehandhabt wird, ist ein anderes Thema - steht 
aber dem nachvollziehbaren Wunsch nicht entgegen, eine Headerdatei 
unangetastet zu lassen.

Nachdem darin ja bereits mit einem #ifdef... vorgesehen ist, auf 
selbstdefinierte Größen sinnvoll zu reagieren, macht es auch gar keinen 
Sinn, darin zu ändern.

von Stefan E. (sternst)


Lesenswert?

Das Ganze wird aber so (ohne Verändern der uart.h) gar nicht 
funktionieren, denn der Code in uart.c wird ja so mit den falschen 
(originalen) Defines arbeiten.

von Klaus W. (mfgkw)


Lesenswert?

Wieso?
Man definiert sich seine Wunschwerte vor dem #include, in der 
Headerdatei wird mit #ifndef UART_RX_BUFFER_SIZE... festgestellt, daß es 
den Wert schon gibt und nicht umdefiniert.
So arbeiten die Headerdatei und main.c mit demselben Wert.
Nach dem #include geht es in main.c mit den richtigen Werten weiter.

Oder habe ich etwas übersehen?

von Stefan S. (stefanst)


Lesenswert?

Vielen Dank für die Antworten!

Ich habe eben ausprobiert was passiert, wenn ich das define in main.c 
vor das include setze. (Habe einfach in ein #warning in das #ifndef 
gesetzt und siehe da, es kommt keine warning, wenn ich das define vor 
das include setze).

Gruß,
Stefan

von Stefan E. (sternst)


Lesenswert?

Klaus Wachtler schrieb:
> So arbeiten die Headerdatei und main.c mit demselben Wert.
> Nach dem #include geht es in main.c mit den richtigen Werten weiter.
>
> Oder habe ich etwas übersehen?

Ja, den Code in uart.c.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
> Das Ganze wird aber so (ohne Verändern der uart.h) gar nicht
> funktionieren, denn der Code in uart.c wird ja so mit den falschen
> (originalen) Defines arbeiten.

Jede Wette, dass er den Code nicht in einer uart.c sondern komplett in 
uart.h hat.

von Stefan S. (stefanst)


Lesenswert?

Hmm... so einfach wars anscheinend doch nicht. Ich habe nun die defines 
aus uart.h auskommentiert und nur in main.c definiert und schon kommt 
ein undeclared-error.

Komme ich nicht drum herum, die defines in uart.h zu ändern? Es ist 
doof, wenn ich nicht in main.c die Puffergröße ändern kann, sondern 
immer die uart.h verändern muss. Sowas wie "globale defines" gibts 
anscheinend nicht (also ein define, das in main geschrrieben wird und 
ebenfalls in uart.c benutzt werden kann. Wahrscheinlich liegt das daran, 
dass uart.c erst einzeln kompiliert wird?!)

Ich nutze die uart.c und uart.h von Peter Fleury für einen ATmega8.

von Karl H. (kbuchegg)


Lesenswert?

Stefan S. schrieb:

> immer die uart.h verändern muss. Sowas wie "globale defines" gibts
> anscheinend nicht

so direkt nicht.
Aber praktisch alle Compiler erlauben es, dass man ihnen auf der 
Command-Line Belegungen für einige #define mitgeben kann.
Dort (in der Projektverwaltung bzw. im Makefile) ist also der Platz wie 
man solche Dinge realisiert. Damit ist dann auch gewährleistet, dass 
alle C-Files, die zum Projekt gehören, mit identischen #define-Werten 
compiliert werden.

> ebenfalls in uart.c benutzt werden kann. Wahrscheinlich liegt das daran,
> dass uart.c erst einzeln kompiliert wird?!)

Bingo.

Daher würde es dir auch nichts bringen, wenn du in main.c andere Werte 
als in uart.c hast. Denn noch schlimmer als ein Header File ändern zu 
müssen ist es, wenn unterschiedliche C-Files mit essentiell wichtigen 
Konstanten unterschiedlich compiliert werden.

von Rolf M. (rmagnus)


Lesenswert?

Stefan S. schrieb:
> Komme ich nicht drum herum, die defines in uart.h zu ändern? Es ist
> doof, wenn ich nicht in main.c die Puffergröße ändern kann, sondern
> immer die uart.h verändern muss.

Warum?

> Sowas wie "globale defines" gibts anscheinend nicht (also ein define, das
> in main geschrrieben wird und ebenfalls in uart.c benutzt werden kann.

Genau dafür ist doch das define in uart.h da. Wenn du in main.c die 
Sachen nochmal definierst, hast du eine Definition nur für main.c und 
dann noch in uart.h eine "globale" für alles andere.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan S. schrieb:

> Und in meiner main.c:

Wenn die Defines schon bestehen, etwa weil uart.h bereits includet wurde 
oder die Defines auf der Kommandozeile geschehen, dann überschreibt man 
die Makros mit:
1
#undef  UART_RX_BUFFER_SIZE
2
#define UART_RX_BUFFER_SIZE 64 // Size of the circular receive buffer,
Damit wird zudem ersichtlich, daß es woanders eine 
Default-Initialisierung gibt.

von Stefan S. (stefanst)


Lesenswert?

Rolf Magnus schrieb:
> Stefan S. schrieb:
>> Komme ich nicht drum herum, die defines in uart.h zu ändern? Es ist
>> doof, wenn ich nicht in main.c die Puffergröße ändern kann, sondern
>> immer die uart.h verändern muss.
>
> Warum?
Weil ich gerne am Ende ein Programm vorliegen haben möchte, in dem ich 
alle "Einstellungen" zentral in main.c treffen kann. Annahme: Nach einem 
Jahr schaue ich mir das Programm mal wieder an, dann wäre es 
schrecklich, erst in allen Dateien nach Definitionen zu suchen...

Karl Heinz Buchegger schrieb:
>> immer die uart.h verändern muss. Sowas wie "globale defines" gibts
>> anscheinend nicht
>
> so direkt nicht.
> Aber praktisch alle Compiler erlauben es, dass man ihnen auf der
> Command-Line Belegungen für einige #define mitgeben kann.
> Dort (in der Projektverwaltung bzw. im Makefile) ist also der Platz wie
> man solche Dinge realisiert. Damit ist dann auch gewährleistet, dass
> alle C-Files, die zum Projekt gehören, mit identischen #define-Werten
> compiliert werden.
Vielen Dank für diesen heißen Tipp :-) Habe die Command-line Optionen in 
AVR Studio 5 gefunden und er kompiliert das Projekt (sowohl main.c, als 
auch uart.c) ohne Probleme!

von Rolf M. (rmagnus)


Lesenswert?

Stefan S. schrieb:
> Rolf Magnus schrieb:
>> Stefan S. schrieb:
>>> Komme ich nicht drum herum, die defines in uart.h zu ändern? Es ist
>>> doof, wenn ich nicht in main.c die Puffergröße ändern kann, sondern
>>> immer die uart.h verändern muss.
>>
>> Warum?
> Weil ich gerne am Ende ein Programm vorliegen haben möchte, in dem ich
> alle "Einstellungen" zentral in main.c treffen kann. Annahme: Nach einem
> Jahr schaue ich mir das Programm mal wieder an, dann wäre es
> schrecklich, erst in allen Dateien nach Definitionen zu suchen...

Wieso suchen? Dein Programm besteht aus Modulen. Eins davon ist uart, 
und da gibt es einen Heder, der alle uart-spezifischen Einstellungen 
beinhaltet.
Oder, wenn dein Programm zu klein ist für so eine Einteilung, baue dir 
einen Konfigurations-Header, in dem das alles drin steht. Wenn du deine 
Einstellungen (in Form von #define) alle in main.c machst, kannst du die 
nämlich auch nur in main.c verwenden.


Karl Heinz Buchegger schrieb:
> Aber praktisch alle Compiler erlauben es, dass man ihnen auf der
> Command-Line Belegungen für einige #define mitgeben kann.
> Dort (in der Projektverwaltung bzw. im Makefile) ist also der Platz wie
> man solche Dinge realisiert. Damit ist dann auch gewährleistet, dass
> alle C-Files, die zum Projekt gehören, mit identischen #define-Werten
> compiliert werden.

Nunja, für zwei oder drei defines finde ich das noch ok, aber wenn du 
einen ganzen Stall davon hast, der dann kommentarlos irgendwo im 
Makefile rumfährt und die Compiler-Kommandozeile unleserlicher macht, 
ist das auch nicht unbedingt das gelbe vom Ei.

von Stefan S. (stefanst)


Lesenswert?

Rolf Magnus schrieb:
> Oder, wenn dein Programm zu klein ist für so eine Einteilung, baue dir
> einen Konfigurations-Header, in dem das alles drin steht. Wenn du deine
> Einstellungen (in Form von #define) alle in main.c machst, kannst du die
> nämlich auch nur in main.c verwenden.

Das hört sich natürlich auch gut an... du meinst eine config.h mit den 
allgemein gültigen Einstellungen erstellen und die in alle anderen 
header-Dateien einbinden?

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:

>> Dort (in der Projektverwaltung bzw. im Makefile) ist also der Platz wie
>> man solche Dinge realisiert. Damit ist dann auch gewährleistet, dass
>> alle C-Files, die zum Projekt gehören, mit identischen #define-Werten
>> compiliert werden.
>
> Nunja, für zwei oder drei defines finde ich das noch ok, aber wenn du
> einen ganzen Stall davon hast, der dann kommentarlos irgendwo im
> Makefile rumfährt und die Compiler-Kommandozeile unleserlicher macht,
> ist das auch nicht unbedingt das gelbe vom Ei.

Bin bei dir.
Unglücklicherweise (für mich), hab ich da nämlich auch noch keine gute 
alternative Lösung dafür. Ein config.h klappt so nicht, weil ich zb die 
uart.c, lcd.c auf eigenen Codelib-Subverzeichnissen halten möchte ohne 
sie jeweils ins laufende Projektverzeichnis kopieren zu müssen. Nur von 
dort geht ein #include aufs jeweilige Projektverzeichnis wieder nicht.

von Andreas D. (rackandboneman)


Lesenswert?

Das hat nichts mit global oder nicht zu tun, sondern damit dass 
Präprozessoranweisungen sequentiell funktionieren... Das kann man auch 
bewusst nutzen ala

#define BLUB 13
 #define BLA 0815
  #include "template.inc"
 #undef BLA

 #define BLA 42
  #include "template.inc"
 #undef BLA
#undef BLUB

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.