Verwendung von #if und #else ?

OP #2484237
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?
OP #2485523
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!
Gast #2486127
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?
OP #2486132
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.
#2486180
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.
#2486199
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.
#2486282
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.
#2486329
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.
#2486334
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.
Gast #2486363
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
OP #2489415
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?
Gast #2489475
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.
OP #2490638
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?
#2490644
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
   }
#2490652
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
Gast #2490654
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:
Gast #2490687
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.
#2490707
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.
#2490717
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 :)
OP #2490834
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?
#2490876
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.
#2491051
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren