Forum: PC-Programmierung Bedingtes Compilieren funktioniert nicht


von Gerhard Z. (germel)


Lesenswert?

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
16
#endif
17
18
main()
19
{
20
  printf("Fahrzeug: %s, Torque: %u\n",FAHRZEUG,TORQUE);
21
}

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

von ... (Gast)


Lesenswert?

Sehr verwunderlich wenn der Koempeiler da ueberhaupt was
zusammengekloeppelt bekommt.

von foo (Gast)


Lesenswert?

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.

von R. Rebentrost (Gast)


Lesenswert?

Du erwartest zu viel von Makros ...

#define VEHICLE 1

#if VEHICLE == 1
...

würde funktionieren.

von Gerhard Z. (germel)


Lesenswert?

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

von foo (Gast)


Lesenswert?

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.

von Gerhard Z. (germel)


Lesenswert?

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

von foo (Gast)


Lesenswert?

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.

von Gerhard Z. (germel)


Lesenswert?

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

von Planlos (Gast)


Lesenswert?

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.

von Gerhard Z. (germel)


Lesenswert?

Danke noch mal an alle, ich mach's jetzt in Anlehnung an foos Beispiel 
so:
1
#include "stdio.h"
2
3
// Fahrzeug definieren aus Liste
4
// BMW, AUDI, VW
5
#define AUDI
6
7
#if defined(BMW)
8
    #define TORQUE 350
9
    #define FAHRZEUG "BMW"
10
#elif defined(AUDI)
11
    #define TORQUE 250
12
    #define FAHRZEUG "Audi"
13
#elif defined(VW)
14
    #define TORQUE 150
15
    #define FAHRZEUG "VW"
16
#else
17
    # error VEHICLE does not match any implemented vehicle
18
#endif
19
20
main()
21
{
22
  printf("Fahrzeug: %s, Torque: %u\n",FAHRZEUG,TORQUE);
23
}

So taugt's mir und es funktioniert.
G

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.