#Define spinnt oder ich spinne

OP #825486
Lesenswert?

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
#825495
Lesenswert?

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

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