Forum: Mikrocontroller und Digitale Elektronik Verwendung von #if und #else ?


von Minty M. (mayflavor)


Lesenswert?

Hi,

ich schreibe für einen Tricore TC1797 in C ein Programm zum 
Sensorauswerten und bin über die Präprozessoranweisungen #if und #else 
gestoßen.
Damit kann man ja scheinbar den Code wählen, der kompiliert werden soll.

Ich habe eine C-Datei über die ich bestimmte Sachen festlegen will.
Ein Beispiel: Soll die Endwertberechnung über Filter stattfinden oder 
nicht? Dazu gibt es einen Parameter.

Im Interrupt soll dann nur der entsprechende Quellcode übersetzt werden.
Beispiel:

#if(Parameter1>0)
function1();
#else
function2();
#endif

Über die C-Datei will ich eine Vielzahl von solchen Optionen einbauen, 
mit denen man das Programm variabel machen kann. Damit nicht in jedem 
Interrupt viele if-Abfragen stattfinden, soll der Compiler nur die 
benötigten Codezeilen übersetzen.

Oder ist das #if nicht für eine solche Verwendung gedacht?
Ist es nur in Kombination mit #define konzipiert?

von Michael H. (michael_h45)


Lesenswert?

http://gcc.gnu.org/onlinedocs/cpp/
http://gcc.gnu.org/onlinedocs/cpp/Conditionals.html#Conditionals
Ist zwar erst mal nur für den gcc, beantwortet aber alle deine Fragen.

von Minty M. (mayflavor)


Lesenswert?

danke, Michael H.
So richtig schlau werd ich aber nicht daraus.

Sagt der Text, dass es teilweise mit manchen Compilern nicht richtig 
geht?

Mein Code sieht z.B. folgendermaßen aus:

#if ((filterAddLength01!=0x00)||(filterMavLength01!=0x00))
put(buffer01,bufferSize01,&posPut01,FADC_uwGetFinalFilterResult(0),&n01) 
;
#else 
put(buffer01,bufferSize01,&posPut01,FADC_uwGetChannelConversionResult(0) 
,&n01);
#endif

Irgendwie scheint er dabei meistens ins else-Statement zu gehen.
Wenn ich die beiden Parameter filterAddLength01 und filterMavLength01 
auf einen anderen Wert als 0x00 setze, scheint er manchmal dieses und 
manchmal jenes zu machen.
Kann leider keinen Zusammenhang ausmachen!

von Rüttiger (Gast)


Lesenswert?

Minty Mint schrieb:
> #if ((filterAddLength01!=0x00)||(filterMavLength01!=0x00))

und wie sind filterAddLength01 und filterMavLength01 definiert?

von Wolfgang (Gast)


Lesenswert?

Minty Mint schrieb:
> #if ((filterAddLength01!=0x00)||(filterMavLength01!=0x00))

Ob dein Präprozessor das alles versteht?

von http://www. (Gast)


Lesenswert?

Wolfgang schrieb:
> Minty Mint schrieb:
>> #if ((filterAddLength01!=0x00)||(filterMavLength01!=0x00))
>
> Ob dein Präprozessor das alles versteht?

Warum nicht? Wenn filterAddLength01 eine Präprozessorkonstante ist passt 
das. Wenn es aber eine Variable ist hat der TO was falsch verstanden...

von Ralf G. (ralg)


Lesenswert?

... ich schreibe für einen Tricore TC1797 in C ein Programm ... Im 
Interrupt soll dann nur der entsprechende Quellcode übersetzt werden 
...

Also irgendwas passt hier nicht zusammen. Oder haue ich da ein paar 
Begriffe durcheinander?

von Michael H. (michael_h45)


Lesenswert?

Wolfgang schrieb:
> Ob dein Präprozessor das alles versteht?
ja
Ralf G. schrieb:
> Oder haue ich da ein paar
> Begriffe durcheinander?
ja

von gaast (Gast)


Lesenswert?

Minty Mint schrieb:
> Mein Code sieht z.B. folgendermaßen aus:
>
> #if ((filterAddLength01!=0x00)||(filterMavLength01!=0x00))
> put(buffer01,bufferSize01,&posPut01,FADC_uwGetFinalFilterResult(0),&n01) ;
> #else
> put(buffer01,bufferSize01,&posPut01,FADC_uwGetChannelConversionResult(0) ,&n01);
> #endif

Woher kommen filterAddLength01 und filterMavLength01? Variablen oder 
#define?

von Minty M. (mayflavor)


Lesenswert?

OK, danke für die Tipps.
Jetzt funktioniert es soweit.
Hatte filterAddLength01 als globale Variable definiert.

Hab das nun zu einem #define gemacht.

Unter dem geposteten Link hab ich nicht alles gelesen.
Wär auch recht viel.

Demnach muss man das immer über #define machen, sonst gehts nicht, oder?
Was für einen Datentyp liefern solche Defines eigentlich?
Soweit ich weiß geht das mit int und long.

von Peter II (Gast)


Lesenswert?

Minty Mint schrieb:
> Was für einen Datentyp liefern solche Defines eigentlich?

überhaupt keine, es sind ja auch keine Variablen. Ist es nur Text.

von Michael H. (michael_h45)


Lesenswert?

Peter II schrieb:
> überhaupt keine, es sind ja auch keine Variablen. Ist es nur Text.
blödsinn.
das sind integer. was ein integer ist, findest du in der dokumentation 
deines compilers.
üblicherweise: 16 bit signed.

von Peter II (Gast)


Lesenswert?

Michael H. schrieb:
> blödsinn.
> das sind integer

klar doch:

#define test "ich bin ein integer"

von (prx) A. K. (prx)


Lesenswert?

Minty Mint schrieb:

> mit denen man das Programm variabel machen kann. Damit nicht in jedem
> Interrupt viele if-Abfragen stattfinden, soll der Compiler nur die
> benötigten Codezeilen übersetzen.

Wenn wie hier die abgefragten Dinge konstant sind, dann wird der 
Compiler die Abfragen bereits bei optimierten Übersetzen auflösen und 
den unmöglichen Code eliminieren.

Exzessive Verwendung von diesen Präprozessor-Direktiven ist nicht 
sonderlich übersichtlich. Wenn solcherart ausgeblendeter Code vom 
Compiler nicht akzeptiert wird, dann sind sie nötig. Andernfalls sind 
normale Abfragen weit lesbarer.

von Michael H. (michael_h45)


Lesenswert?

1
#define foo 5
2
#define bar 4
3
#if (foo < bar)
4
   #warning this is foobar.
willst du mir jetz sagen, 5 und 5 seien text?

von Achim M. (minifloat)


Lesenswert?

Michael H. schrieb:
> das sind integer.

Das sind Textschnipsel, die stupide ersetzt bzw. reingestempelt werden.
1
#define MY_FLOAT 9.6E6
2
#define MY_LONG -65537L
3
#define MY_UNSIGNED_LONG 16000000UL 
4
#define MY_STRING "Hallo Welt\n"

mfg mf

von Michael H. (michael_h45)


Lesenswert?

der c präprozessor kennt üblicherweise kein float, string und sonstiges.
er kann integer verschiedener länge verarbeiten. der rest ist 
textersetzung.

lest die doku.

von Peter II (Gast)


Lesenswert?

Michael H. schrieb:
> willst du mir jetz sagen, 5 und 5 seien text?

ja will ich, und es ist auch so. Warum soll eine 5 kein Text sein?

von Klaus W. (mfgkw)


Lesenswert?

Michael H. schrieb:
> willst du mir jetz sagen, 5 und 5 seien text?

Der PP hält sie tatsächlich erstmal als Text.
Nur im Vergleich mit < wird daraus eine Zahl.

Das sieht man z.B. wenn man eine vermeintliche Zahl mit einem 
merkwürdigen Format definiert (mit führendem + bspw.) und dann wieder 
irgendwie ausgibt, z.B. über # als String: dann taucht die Zahl in ihrem 
ursprünglichen Format auf, und nicht aus einer Zahl in eine 
Standarddarstellung konvertiert.

von Michael H. (michael_h45)


Lesenswert?

Mini Float schrieb:
> Das sind Textschnipsel
DEIN beispiel schon.
der TO will aber die conditionals des präprozessors selbst benutzen. und 
der kann nun mal integer.

von Michael H. (michael_h45)


Lesenswert?

Klaus Wachtler schrieb:
> Der PP hält sie tatsächlich erstmal als Text.
> Nur im Vergleich mit < wird daraus eine Zahl.
nichts andres sag ich doch...

wenn hier jeder meint, er müsse dagegenreden, damit die luft mal 
schwingt, wirds mir zu blöd.
lest die doku, sie gibt mir recht.

von Achim M. (minifloat)


Lesenswert?

Michael H. schrieb:
> lest die doku, sie gibt mir recht.

[...]
Formally, preprocessing numbers begin with an optional period, a 
required decimal digit, and then continue with any sequence of letters, 
digits, underscores, periods, and exponents.
[...]
The purpose of this unusual definition is to isolate the preprocessor 
from the full complexity of numeric constants.
[...]

Erst durch einen Vergleich mit #if oder #ifdef wird veranlasst, dass der 
Textschnipsel als -wie immer auch geartete- Zahl interpretiert und 
verwendet wird.
Ich klink mich aus.

von Sebastian M. (compressed)


Lesenswert?

1
#define debug         1 //0=Debugmodus aus, 1:Debugmodus an
2
3
#if debug
4
  uart_puts("Debugmodus AN");
5
#endif
6
.
7
.
8
.
9
.
10
.
11
.
12
#if debug
13
  alles was sonst noch compiliert werden soll
14
#endif

so?

von (prx) A. K. (prx)


Lesenswert?

Mini Float schrieb:

> Erst durch einen Vergleich mit #if oder #ifdef wird veranlasst, dass der
> Textschnipsel als -wie immer auch geartete- Zahl interpretiert und
> verwendet wird.

Und dort gilt als Daumenregel "Schrott rein Schrott raus". #if 
Statements akzeptieren als Bedingung ziemlich viel Blödsinn ohne sich 
drüber zu beschweren. Das sorgt mitunter für Irritationen, wenn etwas, 
was im "if" Statement als Syntax Error angezeigt würde, vom #if 
kommentarlos gefressen wird. Nicht immer zur Freude des Programmierers.

von gaast (Gast)


Lesenswert?

1
#define DEBUG
2
#ifdef DEBUG
3
//Debugmodus
4
#endif

reicht vollig und ist einfacher und deshalb auch verbreiteter (in 
sämtlichen üblichen Headerfiles z.B.).

von (prx) A. K. (prx)


Lesenswert?

Sebastian M. schrieb:

> so?

Im Prinzip ja, aber dies führt zu recht hässlichem Code, wenn alle paar 
Zeilen so eine #if/#endif Klammer steht.

Besser beispielsweise:
1
#if debug
2
# define TRACE(s) uart_puts(s)
3
#else
4
# define TRACE(s)
5
#endif
6
7
   ...
8
   TRACE("Debugmodus AN");
9
   ...
10
   TRACE("Panic!");

Weil man so beliebig viel Trace-Kram einstreuen kann, ohne dass es 
unübersichtich wird.

Freunde von printf können das auch ohne varargs-Makros haben:
1
#if debug
2
# define TRACE(s) printf s
3
#else
4
# define TRACE(s)
5
#endif
6
7
  ...
8
  TRACE(("Version vom %s", __DATE__));
9
  ...
Man beachte die Klammern.

von Sebastian M. (compressed)


Lesenswert?

danke, sieht gut aus :)

von holger (Gast)


Lesenswert?

>Freunde von printf können das auch ohne varargs-Makros haben:

>#if debug
># define TRACE(s) printf s
>#else
># define TRACE(s)
>#endif

Geht auch so

#if debug
# define TRACE printf
#else
# define TRACE(...)
#endif

von Minty M. (mayflavor)


Lesenswert?

Danke für die Hilfe!

Das ist echt ein Spitzenboard hier!
Man kriegt einfach immer Antworten und eine brauchbare ist stets dabei.

Soll ich jetzt eigentlich diese #if und #else verwenden oder ist das 
sowieso hinfällig, wenn man darüber nur #defines abfragt?

prx schrieb:
"Wenn wie hier die abgefragten Dinge konstant sind, dann wird der
Compiler die Abfragen bereits bei optimierten Übersetzen auflösen und
den unmöglichen Code eliminieren.

Exzessive Verwendung von diesen Präprozessor-Direktiven ist nicht
sonderlich übersichtlich. Wenn solcherart ausgeblendeter Code vom
Compiler nicht akzeptiert wird, dann sind sie nötig. Andernfalls sind
normale Abfragen weit lesbarer."

Soll ich nun if oder #if verwenden?

von (prx) A. K. (prx)


Lesenswert?

Wenn beides geht: "if". Konkreter wird es mangels funktionierender 
Glaskugel nicht.

von W.S. (Gast)


Lesenswert?

Minty Mint schrieb:
> Soll ich jetzt eigentlich diese #if und #else verwenden oder ist das
> sowieso hinfällig, wenn man darüber nur #defines abfragt?

Meine Meinung: Schreibe deine Programme möglichst ohne #if und ohne 
#ifdef
Das ist Präprozessorakrobatik und dient eigentlich nur dazu, aus einigen 
ähnlichen Quellen eine einzige Quelle zu machen. Am Ende wird das alles 
nur unübersichtlich und schwerfällig. Wenn du für 2 ähnliche Probleme 2 
unterschiedliche Programme brauchst, dann mach für jedes Problem eines. 
Andererseits kann es ja vorkommen, daß dein Programm verschiedene Fälle 
beachten muß (zur Laufzeit, wohlgemerkt), dann ist #if regelrecht 
falsch.

Ich hatte schon Quellen, wo sich #ifdef .... #endif Konstrukte über 
mehrere verschiedene Quellen hinzogen, so daß man am Ende gar nicht mehr 
nachvollziehen konnte, was denn tatsächlich im erzeugten Code landete. 
Das war ein Obermist.

Ach ja, nochwas: Spaghetticode (Relikt von BASIC) und die Verwendung von 
goto_ in C sind was _verschiedenes. Also schreibe dort, wo es sachlich 
hinpaßt besser goto und vermeide sowas wie while(1){....};

W.S.

von Minty M. (mayflavor)


Lesenswert?

hm, mir wurde 2 mal beigebracht, dass man keinesfalls goto verwenden 
soll.
deswegen stelle ich auch deine andere Antwort in Frage, W.S..

Letztendlich brauche ich für verschiedene Anwendungsfälle verschiedenen 
Code.

Die Frage ist dann: Wird bei normalem "if" auch sicher nur der nötige 
Code übersetzt oder nicht?

Oder soll ich auf Nummer sicher gehen mit #if?
Was meint ihr?
Wozu gibt es dann überhaupt die #if-Funktion, wenn der Compiler sowieso 
den überflüssigen Code wegkürzt?

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:

> Ach ja, nochwas: Spaghetticode (Relikt von BASIC) und die Verwendung von
> goto_ in C sind was _verschiedenes. Also schreibe dort, wo es sachlich
> hinpaßt besser goto und vermeide sowas wie while(1){....};

Das ist mal ein recht seltsamer Tipp. Falls du das meinst
1
   loop:
2
      ...
3
      goto loop;
an Stelle des allgemein üblichen
1
   while(1) {
2
      ...
3
   }
oder
1
   for (;;) {
2
      ...
3
   }

von (prx) A. K. (prx)


Lesenswert?

Minty Mint schrieb:

> Die Frage ist dann: Wird bei normalem "if" auch sicher nur der nötige
> Code übersetzt oder nicht?

Ja, wenn der Compiler etwas taugt.

> Oder soll ich auf Nummer sicher gehen mit #if?

> Wozu gibt es dann überhaupt die #if-Funktion, wenn der Compiler sowieso
> den überflüssigen Code wegkürzt?

Weil es Fälle gibt, in denen man mit if() nicht weiter kommt. 
Beispielsweise bei
1
#if linux
2
  #include <linux/sonstwas.h>
3
#elif windows
4
  #include <win32.h>
5
#else
6
  #error Mac???
7
#endif

von Peter II (Gast)


Lesenswert?

A. K. schrieb:
> Das ist mal ein recht seltsamer Tipp. Falls du das meinst

nein, er meint vermutlich soetwas:
1
while(1) {
2
3
   if ( x == y ) {
4
      beak;
5
   }
6
7
   if ( a== b) {
8
      beak;
9
   }
10
}

statt:
1
if ( x == y ) {
2
  goto next;
3
}
4
5
if ( a== b) {
6
   goto next:
7
}
8
next:

von (prx) A. K. (prx)


Lesenswert?

Peter II schrieb:

> nein, er meint vermutlich soetwas:

D´accord. Bei solchen Konstruktionen ist goto sinnvoll, jedenfalls wenn 
sie grösser sind als dieses Beispiel.

von W.S. (Gast)


Lesenswert?

Minty Mint schrieb:
> hm, mir wurde 2 mal beigebracht, dass man keinesfalls goto verwenden
> soll.
> deswegen stelle ich auch deine andere Antwort in Frage, W.S..

Tja, sowas stimmt mich ein bissel traurig. Dir wurde es also SO 
beigebracht... hmm in meinem Inneren grummelt die Frage, ob die jungen 
Leute heutzutage etwas gelehrt bekommen, den Sinn verstanden und es 
somit gelernt haben oder ob sie lediglich dressiert bzw. abgerichtet 
werden.

Im Klartext: das Wort "goto" gehört zum Grundwortschatz von C und vieler 
anderer Programmiersprachen. Du darfst deinen Lehrern einen schönen Gruß 
von mir ausrichten und daß sie sich nach 30 jährigem Tiefschlaf mal 
aufraffen mögen, ihre Köpfe endlich auszumisten. Damals war BASIC die 
schlichtweg überragende Programmiersprache auf allem, was man heute "PC" 
nennen würde. Selbst der Ur-IBM-PC hatte zuallererst einen residenten 
Basicinterpreter drin. Da aber das damalige Basic im Wesentlichen auf 
Zeilennummern beruhte, war ein buntes Durcheinander von GOTO's 
schlichtweg nötig.

Aus dieser Zeit stammt der Rat, "goto" möglichst zu vermeiden und sich 
der anderen Konstrukte zu bedienen, die die damals aufkommenden neuen 
Programmiersprachen Pascal und C boten: case bzw. switch, do while, 
repeat until und so.

Pauschal das goto zu verteufeln und dies zu verabsolutieren ist reiner 
Unsinn. Aber offenbar wird den jungen Leuten heutzutage eben genau 
dieser Unsinn eingebleut und diese verinnerlichen das ohne es kritisch 
zu hinterfragen. Kurzum, sowas stimmt mich traurig.

W.S.

von Michael H. (michael_h45)


Lesenswert?

Minty Mint schrieb:
> Letztendlich brauche ich für verschiedene Anwendungsfälle verschiedenen
> Code.
und dann stellt sich halt die frage: kannst du die fälle erst zur 
laufzeit oder schon zur compilezeit unterscheiden?

> Die Frage ist dann: Wird bei normalem "if" auch sicher nur der nötige
> Code übersetzt oder nicht?
grundsätzlich: ja, wird mitübersetzt.

> Oder soll ich auf Nummer sicher gehen mit #if?
es wäre hilfreich, wenn du diese recht einfache entscheidung selbst 
fällen würdest, nachdem du denn verstanden hast, was #if und if denn nun 
sind.
#if ist eine reine präprozessoranweisung. klammerst du befehle in ein 
#if-conditional, das nicht erfüllt ist, behandelt es der compiler, als 
wäre es nicht da.

von Michael H. (michael_h45)


Lesenswert?

W.S. schrieb:
> hmm in meinem Inneren grummelt die Frage, ob die jungen
> Leute heutzutage etwas gelehrt bekommen, den Sinn verstanden und es
> somit gelernt haben oder ob sie lediglich dressiert bzw. abgerichtet
> werden.
Das wird bei dir wie bei mir nicht anders gewesen sein: man bekommt 
nicht alles breit erklärt oder häppchenweise vorgekaut. Wer Interesse an 
seinem Werdegang hat, informiert sich eigenständig und versucht nicht 
nur auswendig zu lernen, sondern eben zu verstehen. Wer diese 
Eigenverantwortung nicht annimmt, ist selbst schuld.
Mein Arbeitsplatz fühlt sich nach so einem Thread immer ein bisschen 
sicherer an :)

von Minty M. (mayflavor)


Lesenswert?

Michael H. schrieb:
> Minty Mint schrieb:
>> Letztendlich brauche ich für verschiedene Anwendungsfälle verschiedenen
>> Code.
> und dann stellt sich halt die frage: kannst du die fälle erst zur
> laufzeit oder schon zur compilezeit unterscheiden?

die fälle sind schon zur compilezeit klar.


>> Die Frage ist dann: Wird bei normalem "if" auch sicher nur der nötige
>> Code übersetzt oder nicht?
> grundsätzlich: ja, wird mitübersetzt.

das ist eine etwas widersprüchliche antwort. das "ja" sagt, es wird nur 
der nötige Code übersetzt, das "wird mitübersetzt" sagt, dass der 
unnötige Rest auch übersetzt wird.
wie nun?

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:

> Damals war BASIC die schlichtweg überragende Programmiersprache

Die "goto" Debatte geht wesentlich auf ältere Sprachen wie FORTRAN und 
COBOL zurück.

von Michael H. (michael_h45)


Lesenswert?

Minty Mint schrieb:
> das ist eine etwas widersprüchliche antwort.
Stimmt, entschuldigung!
Was du hinschreibst, wird übersetzt, außer der Compiler kann sicher 
feststellen, dass das Conditional nur einen Zustand einnimmt. Dann 
kann es sein, dass der Compiler optimiert.
z.B.:
1
const int festwert = 10;
2
if(festwert < 5)
3
  a();
4
else
5
  b();
Wenn er aber nicht weiß, was mit Variable passieren kann, wird er beide 
Fälle und das if dazu übersetzen.
Dass muss aber keineswegs immer so sein. Was dein Compiler genau macht, 
musst du nachlesen oder ausprobieren.

von Klaus W. (mfgkw)


Lesenswert?

Minty Mint schrieb:
> wie nun?

Also wenn du bis hier noch nicht den Unterschied zwischen Präprozessor 
und Compiler mitbekommen hast, würde ich es dir nicht vorwerfen.

Aber daß du trotzdem bis jetzt immer noch nicht selbst angefangen hast 
dich schlau zu machen, z.B. mit einem Buch, zeigt deutlich, daß es 
einfach sinnlos ist dir hier alles vorzukauen.

Was es mit #if auf sich hat, ist erstens elementar für die 
C-Programmierung, und zweitens genau deshalb in jedem C-Buch 
beschrieben.

Wieso sollen die Leute sich hier mehr Mühe geben als du selbst - für 
deine Interessen?

Und wie willst du weitermachen mit Programmieren? Bei jedem Pups hier 
fragen und alles erklären lassen?

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.