#Define spinnt oder ich spinne

OP #825486
Hallo zusammen, ich verzweifele an folgendem Problem, brauche Hilfe:

-----------------
int16_t adcval

#define adcvalMaxY 230
#define adcvalMinY  30

#define MiddleY ((adcvalMaxY - adcvalMinY)/2) + adcvalMinY
//#define MiddleY 130

Wenn ich nun die folgenden Audrücke berechne (mit adcval = 155) dann 
ergibt

(adcval - MiddleY) den Wert  85
(MiddleY - adcval) den Wert -25

Wenn ich nun umkommentiere

//#define MiddleY ((adcvalMaxY - adcvalMinY)/2) + adcvalMinY
#define MiddleY 130

dann ergibt

(adcval - MiddleY) den Wert  25
(MiddleY - adcval) den Wert -25


Was ist denn hier los ??

Ich bin total ratlos!

Grüsse
OP
Autsch - jetzt habe ich es kapiert ...!

Der Pre-Processor ersetzt den Ausdruck

(adcval - MiddleY)

zu ( adcval - ((230 - 30)/2) + 30  ) ...

und nicht zu

zu ( adcval - ( ((230 - 30)/2) + 30) )

Gefährliche Falle ...!

Danke
Yep.
Wie du schon bemerkt hast, ist es immer eine gute Idee
ein Makro zu Klammern wenn es eine Formel darstellen soll.

Aber es gibt noch mehr Fallen mit Makros.

#define DOUBLE(x)  (2 * x)

und jetzt lass mal berechnen

   i = 5;
   j = DOUBLE(i+1)

Das Ergebnis ist nicht 12, sondern 11.
Die Makroexpansion zeigt auch warum. Aus DOUBLE(i+1)
wird
   j = ( 2 * i+1 );
und Aufgrund der Matheregeln wird das als (2*i)+1
gerechnet.

Lösung:
#define DOUBLE(x) ( 2 * (x) )

Das ist aber nicht alles. Es gibt noch mehr. Gefährlich wird
es auch immer dann, wenn ein Makroargument in der Expansion
2 mal vorkommt

#define MAX(x,y) ( (x) < (y) ? (y) : (x) )

und das wendest du mal auf

   i = 5;
   j = 6;
   k = MAX(i++,j++)

an. Welches sind die Werte von i und j nach der Maximumbestimmung?
i hat dann den Wert 6, aber j hat den Wert 8!

Aus diesen Gründen ist man bei Formeln meist mit einer Funktion
auf der besseren Seite

int max( int x, int y )
{
  return x < y ? y : x;
}

Da gibt es keine derartigen überraschenden Effekte. Und da der Compiler
solche Funktionen in den meisten Fällen inlinen wird, hat man auch
keinen Laufzeit-Penalty.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.