Hallo Forengemeinde,
irgendwie schaffe ich es nicht, meinem Compiler (gcc) das bedingte
Compilieren anzugewöhnen. Habe offensichtlich Verständnissprobleme.
Habe einen kurzen Beispielcode geschrieben, um das ganze zu
demonstrieren. Der Code hat keinen praktischen Nährwert. Here we go:
1
#include"stdio.h"
2
3
#define VEHICLE AUDI
4
5
#if VEHICLE == BMW
6
#define TORQUE 350
7
#define FAHRZEUG "BMW"
8
#elif VEHICLE == AUDI
9
#define TORQUE 250
10
#define FAHRZEUG "Audi"
11
#elif VEHICLE == VW
12
#define TORQUE 150
13
#define FAHRZEUG "VW"
14
#else
15
# error VEHICLE does not match any implemented vehicle
Ich möchte vor dem Compilieren in der ersten #define Anweisung das
Fahrzeug definieren und erwarte, dass der Compiler nur den
entsprechenden Zweig compiliert. Macht er aber nicht, die Ausgabe ist
immer
Fahrzeug: BMW, Torque: 350
unabhängig davon, welches Fahrzeug ich eingetragen habe.
Irgendwie muss doch in den Beispielen, die man so ließt, z.B.
1
#if SYSTEM == Linux
das Macro SYSTEM belegt worden sein.
Bin für jeglichen Tip dankbar.
Gerhard
Das liegt an einer bestenfalls merkwürdigen Eigenschaft von C (oder GCC
oder sonstwas).
AUDI, BMW etc hast du nicht als Makros vorab definiert, also weiß der
nicht was damit anzufangen ist.
Dokumentiert ist:
"Identifiers that are not macros, which are all considered to be the
number zero"
( https://gcc.gnu.org/onlinedocs/cpp/If.html#If )
d.h. #if VEHICLE == BMW wird zu #if AUDI == BMW und da beide Makros
nicht definiert sind, werden sie als 0 angenommen. Der Vergleich passt
damit und FAHRZEUG wird damit "BMW".
Ich finde es auch etwas bescheuert, dass das keine Warning erzeugt, aber
das war eben ihr Hack dafür:
"This allows you to write #if MACRO instead of #ifdef MACRO, if you know
that MACRO, when defined, will always have a nonzero value."
Kann man von halten was man will, aber da liegt der Fehler.
Zunächst mal Danke für die schnelle Antwort. Ich blicke aber immer noch
nicht durch. Im K&R steht unter Macro Substitution (S.89):
A definition has the form
1
#define name replacement text
It calls for a macro substitution of the simplest kind - subsequent
occurrences of the token name will be replaced by the replacement text.
Das klinkt doch nach Macro Definition?!
Bitte um ein Beispiel, wie ich für das immer wieder zu findede Beispiel
1
#if SYSTEM == BSD
2
#define HDR "bsd.h"
3
#endif
SYSTEM belegen kann in Fällen, wo das nicht der Compiler übernimmt.
Gerhard
Dieses merkwürdige Verhalten haben sich übrigens nicht die GCC-Leute
ausgedacht, das steht so im Standard drin.
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf Seite 148 (160
im PDF). Ich bleibe dabei dass ich es für unintuitiv halte.
Ich würde das so umschreiben:
1
#define VEHICLE_BMW
2
3
#if defined(VEHICLE_AUDI)
4
...
5
#elif defined(VEHICLE_BMW)
6
...
Dann musst du AUDI, BMW etc nicht vorab als Konstanten definieren, hast
also auch keine Doppelung.
Danke foo, damit kann ich leben. Aus Neugier wüsste ich trotzdem gerne,
wie sich SYSTEM belegen lässt, wenn's der Compiler nicht tut, um obiges
Beispiel selber programmieren zu können. Was expandiert denn da
#if SYSTEM == BSD
der Präprozessor?
Gerhard
Gerhard Z. schrieb:> wie sich SYSTEM belegen lässt, wenn's der Compiler nicht tut, um obiges> Beispiel selber programmieren zu können. Was expandiert denn da> #if SYSTEM == BSD> der Präprozessor?
Entweder du belegst es selbst oder niemand tut es. Dann wirds im
Vergleich zur Zahl 0.
Vielleicht hat jemand einen Header eingebunden in dem BSD, LINUX, ...
vorab zu Werten ungleich 0 #define'd wurden. Dann klappt das und es kann
auch abgefragt werden ob SYSTEM nicht definiert wurde, weil dann nämlich
0 == 1, 0 == 2 ... eben falsch ist.
Ich selbst kenne jedenfalls nur die Makros _linux_, _FreeBSD_,
_WIN32, ... die eben definiert sind oder nicht, jenachdem für was man
gerade baut. Dieses SYSTEM scheint eine eigene Bastelei von irgendwem zu
sein.
foo schrieb:> Dieses SYSTEM scheint eine eigene Bastelei von irgendwem zu> sein.
Ja, der IRGENDWEM ist entweder K oder R ;-) steht so als Beispiel 2
Seiten weiter in der C-Fiebel von K & R unter Conditional Inclusion.
Ich hätte halt gerne (entweder auf der Kommandozeile bzw. im Makefile)
das Fahrzeug definiert ohne ein kryptisches VEHICLE_ davor. Na ja, dann
halt nicht.
Danke nochmal.
Gerhard
Gerhard Z. schrieb:> das Fahrzeug definiert ohne ein kryptisches VEHICLE_ davor. Na ja, dann> halt nicht.
Mach halt erstmal irgendwo:
#define AUDI 1
#define VW 2
#define BMW 3
#define FIAT 4
...
Danach funktioniert dein allererstes Beispiel.