In unserer gesamten C-Code-Basis wird jedes Makro folgendermaßen definiert:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
Was ist der Grund für diese Definitionsprüfungen, anstatt nur die Makros zu definieren?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
Ich kann diese Praxis nirgendwo im Internet erklären.
c
macros
c-preprocessor
ifndef
Trevor Hickey
quelle
quelle
Antworten:
Auf diese Weise können Sie die Makros beim Kompilieren überschreiben:
Die Definitionen in der Header-Datei werden als Standard verwendet.
quelle
Stellen Sie sich diese Situation vor, wie ich im Kommentar sagte:
foo.h
defs.h
bar.c
Wird gedruckt
44
.Wenn die Bedingung
ifndef
jedoch nicht vorhanden wäre, würde das Ergebnis Kompilierungswarnungen zur Neudefinition von MACRO sein und es wird gedruckt64
.quelle
ifdef
, um eine Neudefinition zu vermeiden).#infdef
s als "Fallback" - oder "Standard" -Werte verwendet. Grundsätzlich gilt: "Wenn der Benutzer es konfiguriert hat, ist dies in Ordnung. Wenn nicht, verwenden wir einen Standardwert."#defines
in einem Bibliotheksheader haben, die Teil des ABI der Bibliothek sind, sollten Sie sie nicht einschließen#ifndef
. (Oder besser, verwenden Sie eineenum
). Ich wollte#ifndef
nur klarstellen , dass dies nur dann angemessen ist, wenn eine benutzerdefinierte Definition für etwas in einer Kompilierungseinheit vorhanden ist, eine andere jedoch nicht. Wenna.c
Header in einer anderen Reihenfolge als enthalten sindb.c
, erhalten sie möglicherweise andere Definitionen vonmax(a,b)
und eine dieser Definitionen kann mit brechenmax(i++, x)
, während die andere möglicherweise temporäre Elemente in einem GNU-Anweisungsausdruck verwendet. Zumindest immer noch verwirrend!#ifdef FOO
#error FOO already defined!
#endif
#define FOO x
Ich kenne den Kontext nicht, aber dies kann verwendet werden, um dem Benutzer die Verfügbarkeit zu geben, die durch diese Makrodefinitionen festgelegten Werte zu überschreiben. Wenn der Benutzer explizit einen anderen Wert für eines dieser Makros definiert, wird dieser anstelle der hier verwendeten Werte verwendet.
In g ++ können Sie beispielsweise das
-D
Flag während der Kompilierung verwenden, um einen Wert an ein Makro zu übergeben.quelle
Dies geschieht, damit der Benutzer der Header-Datei die Definitionen aus seinem Code oder aus dem -D-Flag des Compilers überschreiben kann.
quelle
Jedes C-Projekt befindet sich in mehreren Quelldateien. Wenn Sie an einer einzelnen Quelldatei arbeiten, scheinen die Überprüfungen (und tatsächlich) keinen Sinn zu haben. Wenn Sie jedoch an einem großen C-Projekt arbeiten, empfiehlt es sich, vor dem Definieren einer Konstante nach vorhandenen Definitionen zu suchen. Die Idee ist einfach: Sie benötigen die Konstante in dieser bestimmten Quelldatei, sie wurde jedoch möglicherweise bereits in einer anderen definiert.
quelle
Sie können sich ein Framework / eine Bibliothek vorstellen, die dem Benutzer eine Standardvoreinstellung gibt, mit der der Benutzer sie kompilieren und bearbeiten kann. Diese Definitionen sind in verschiedenen Dateien verteilt, und dem Endbenutzer wird empfohlen, die Datei config.h einzuschließen, in der er die Werte konfigurieren kann. Wenn der Benutzer einige Definitionen vergessen hat, kann das System aufgrund der Voreinstellung weiterarbeiten.
quelle
Verwenden von
Ermöglicht dem Benutzer, den Wert des Makros mithilfe des Befehlszeilenarguments (in gcc / clang / VS) zu definieren
-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.Es gibt noch einen weiteren wichtigen Grund. Es ist ein Fehler, ein Präprozessor-Makro anders zu definieren. Siehe diese Antwort auf eine andere SO-Frage . Ohne die
#ifndef
Überprüfung sollte der Compiler einen Fehler erzeugen, wenn-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
er als Befehlszeilenargument im Compileraufruf verwendet wird.quelle