#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