mikrocontroller.net

Forum: Compiler & IDEs #Define spinnt oder ich spinne


Autor: John Schmitz (student)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: John Schmitz (student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: John Schmitz (student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Dank an Alle, Eure Hinweise waren sehr hilfreich.

Grüsse

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.