Forum: Mikrocontroller und Digitale Elektronik Präprozess Makro >>> Fehler: undeclared


von __Son´s B. (bersison)


Angehängte Dateien:

Lesenswert?

Hallo.
Stehe gerade auf dem Schlauch;

Beim Kompilieren wird folgender Fehler angezeigt
'port' und 'mask' undeclared
in der Zeile
#define SET_BIT (port,mask) ((port) |= (1<<mask))

Daher habe ich verschiedene Präproz.-Aufrufe ausprobiert - ohne Erfolg.

Hatte schon ein paar mal den Präprozessor Makro genau so geschrieben - 
Funktionierte immer.

von (prx) A. K. (prx)


Lesenswert?

#define SET_BIT(port,mask) ((port) |= (1<<mask))

> Hatte schon ein paar mal den Präprozessor Makro genau so geschrieben

Sicher nicht mit Leerzeichen zwischen Name und Klammer. Beim 
Präprozessor ist das nicht zulässig.

: Bearbeitet durch User
von __Son´s B. (bersison)


Lesenswert?

Stimmt! Danke!

von __Son´s B. (bersison)


Lesenswert?

Noch einen Fehler;
#define OBER_BEREICH(1023/15*11.5)
hier kommt der Fehler; '1023' nicht zulässig!
Darf im Prä.Macro keine Formelberechnung stehen?

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

da kommt das Leerzeichen nun doch hin :)

von __Son´s B. (bersison)


Lesenswert?

???
Wie unterscheiden sich die Präproz.?
Geht es darum, ob Werte zurück gegeben werden oder irgend etwas 
ausgelöst wird?

von __Son´s B. (bersison)


Lesenswert?

Ich sehe auch gerade, das ich hier die Klammer weglassen kann.

von Speckbert (Gast)


Lesenswert?

A. K. schrieb:
> #define SET_BIT(port,mask) ((port) |= (1<<mask))

Hier ist ein Leerzeichen nach "SET_BIT" falsch, da es sich um ein Makro 
mit "port" und "mask" als Parameter handelt.

__Son´s B. schrieb:
> #define OBER_BEREICH (1023/15*11.5)

Hier muss ein Leerzeichen nach "OBER_BEREICH" eingefügt werden, da es 
sich nicht um ein Makro sondern um eine Wertdefinition handelt.

von Rolf M. (rmagnus)


Lesenswert?

Speckbert schrieb:
> __Son´s B. schrieb:
>> #define OBER_BEREICH (1023/15*11.5)
>
> Hier muss ein Leerzeichen nach "OBER_BEREICH" eingefügt werden, da es
> sich nicht um ein Makro sondern um eine Wertdefinition handelt.

Natürlich handelt es sich um ein Makro, allerdings um eines ohne 
Parameter.

__Son´s B. schrieb:
> ???
> Wie unterscheiden sich die Präproz.?
> Geht es darum, ob Werte zurück gegeben werden oder irgend etwas
> ausgelöst wird?

Nein, es geht darum, ob du an dein Makro Parameter übergeben willst. In 
dem Fall muss die Parameterliste mit ihren Klammern ohne Leerzeichen 
nach dem Namen stehen. Wenn dagegen die Klammer Teil des Inhalts des 
Makros ist, muss sie durch das Leerzeichen abgegrenzt werden. Irgendwie 
muss der Präprozessor das ja unterscheiden können.
Deshalb die Fehlermeldung bei:

__Son´s B. schrieb:
> #define OBER_BEREICH(1023/15*11.5)

Der Präprozessor erwartet in den Klammern eine Parameterliste und stellt 
dann fest, dass 1023 kein gültiger Parametername ist.

von __Son´s B. (bersison)


Lesenswert?

OK!

Noch zwei Grundlagen, die ich nicht ganz zuordnen kann;
--1--
#define SET_BIT(port,mask) ((port) |= (1<<mask))
#define CLR_BIT(port,mask) ((port) &= ~(1<<mask))
#define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1)) 
(SET_BIT(PORTB,PB2))

Fehlermeldung für Zeile LED_LOW.
Darf ein Macro ein anderes Macro nicht direkt aufrufen?

--2--
In ADC_Init() warnt der Komp., dass "messwert" deklariert, aber nicht 
benutzt wird.
  uint16_t messwert;
Hier wird diese Var. in der letzten Zeile zugwiesen;
  messwert = ADCW;
Wie begründet sich die Warnmeldung?

von Kirsch (Gast)


Lesenswert?

__Son´s B. schrieb:
> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))

Einfach so:
#define LED_LOW() (CLR_BIT(PORTB,PB1))


zu 2
nicht verwendet oder nicht gelesen?

von Rolf M. (rmagnus)


Lesenswert?

__Son´s B. schrieb:
> OK!
>
> Noch zwei Grundlagen, die ich nicht ganz zuordnen kann;
> --1--
> #define SET_BIT(port,mask) ((port) |= (1<<mask))
> #define CLR_BIT(port,mask) ((port) &= ~(1<<mask))
> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))
> (SET_BIT(PORTB,PB2))
>
> Fehlermeldung für Zeile LED_LOW.

Gleicher Fehler wie vorher. Du gibst "CLR_BIT(PORTB,PB0)" als 
Parameterliste für dein Makro LED_LOW an. Das ergibt aber nicht viel 
Sinn.

> Darf ein Macro ein anderes Macro nicht direkt aufrufen?

Doch, darf es.

> --2--
> In ADC_Init() warnt der Komp., dass "messwert" deklariert, aber nicht
> benutzt wird.
>   uint16_t messwert;
> Hier wird diese Var. in der letzten Zeile zugwiesen;
>   messwert = ADCW;
> Wie begründet sich die Warnmeldung?

Wird der Inhalt denn irgendwann auch mal wieder gelesen? Eine Variable, 
in den ich einen Wert nur reinschreibe, ohne ihn nachher je wieder 
anzufassen, ist sinnlos.

von (prx) A. K. (prx)


Lesenswert?

__Son´s B. schrieb:
> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))
> (SET_BIT(PORTB,PB2))

Was soll das darstellen?

> Darf ein Macro ein anderes Macro nicht direkt aufrufen?

Doch.

> Wie begründet sich die Warnmeldung?

Möglicherweise weil du zwar einen Wert reinschreibst, aber sonst mit
"messwert" nichts passiert?

von __Son´s B. (bersison)


Lesenswert?

Kirsch schrieb:
> Einfach so:
> #define LED_LOW() (CLR_BIT(PORTB,PB1))
Funktioniert leider auch nicht!

A. K. schrieb:
> Was soll das darstellen?
Vereinfachung der Abfolge LED/high aus, LED/mid aus, LED/low ein

Alternative wäre aufwendiger;
main()...
SET_BIT(PORTB,PB0);
CLR_BIT(PORTB,PB1);
CLR_BIT(PORTB,PB2);
und das immer wieder, je nach Schaltungszustand.

Kirsch schrieb:
> zu 2
> nicht verwendet oder nicht gelesen?
In der Tat, ein Wert wird ausgelesen und in diese Var geschrieben, aber 
nicht weiter verwendet.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

__Son´s B. schrieb:
> Kirsch schrieb:
>> Einfach so:
>> #define LED_LOW() (CLR_BIT(PORTB,PB1))
> Funktioniert leider auch nicht!

"Funktioniert nicht" ist keine adäquate Fehlerbeschreibung.
Das sieht für mich so korrekt aus.

von (prx) A. K. (prx)


Lesenswert?

__Son´s B. schrieb:
> Funktioniert leider auch nicht!

Diesmal fehlen mindestens die ; zwischen den Statements.

: Bearbeitet durch User
von Mein grosses V. (vorbild)


Lesenswert?

__Son´s B. schrieb:
> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))
> (SET_BIT(PORTB,PB2))
>
> Fehlermeldung für Zeile LED_LOW.

Das ist ja auch totaler Mist.

1.:
A. K. schrieb im Beitrag #4421150:
> Da fehlt mal wieder das Lerrzeichen.

2.:

Der Aufruf ist
1
LEDLOW;

Daraus wird:
1
PORTB &= ~(1 << PB0) PORTB &= ~(1 << PB1) PORTB |= (1 << PB2) ;

Fällt dir auf, was da fehlt?
Rictig! Hinter den ersten beiden Anweisungen fehlt das Semikolon.


1
#define SETLOW do{CLR_BIT(PORTB,PB0);\
2
          CLR_BIT(PORTB,PB1);\
3
          CLR_BIT(PORTB,PB0);}while(0)

So macht man das.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Generell ist es sinnvoll, sich mal zu überlegen, was nach einer 
Makro-Ersetzung rauskommt und zu scahuen, ob das einen Sinn ergibt. 
Damit kommt man zumindest schneller zum Ziel als durch hin- und 
herschieben von Leerzeichen und mal probieren, ob's der Compiler 
schluckt.

von __Son´s B. (bersison)


Lesenswert?

Ok, so passt´s

#define LED_LOW (CLR_BIT(PORTB,PB0)); \
(CLR_BIT(PORTB,PB1)); \
(SET_BIT(PORTB,PB2))

LED_LOW;

von Mein grosses V. (vorbild)


Lesenswert?

__Son´s B. schrieb:
> Ok, so passt´s

Nein, das ist auch Mist.

Überleg dir mal, was passiert, wenn du schreibst:
1
if(blabla)LEDLOW;

Setz das in eine do{}while(0) Schleife. Alles andere macht nur Probleme.
Die Schleife wird vom Compiler komplett wegoptimiert. Die ist also gar 
nicht da.

von __Son´s B. (bersison)


Lesenswert?

Mein grosses V. schrieb:
> Überleg dir mal, was passiert, wenn du schreibst:
while(1)
{
mit_wert = ADC_Read_Avg(3,64);
if (mit_wert > OBER_BEREICH) { LED_HIGH; }
if (mit_wert < UNTER_BEREICH) { LED_LOW; }
else { LED_MID; }
}

Nach meinm Verständnis, wird "mit_wert" in einer Dauerschleife 
ausgewertet und danach den 3 Bedingungen zu geordnet. Was soll daran 
"Mist" sein?

von (prx) A. K. (prx)


Lesenswert?

Wenn du immer alles richtig machst, dann ist alles richtig. Zum Problem 
wird es, wenn du eines Tages mal die {} Klammern weglässt.

von Mein grosses V. (vorbild)


Lesenswert?

__Son´s B. schrieb:
> if (mit_wert > OBER_BEREICH) { LED_HIGH; }

Das habe ich auch nicht geschrieben, sondern das:
1
if(blabla) LEDHIGH;

Und daraus wird:
1
if(blabla) Anweisung1;
2
Anweisung2;
3
Anweisung3;

D.h., daß Anweisung1 in Abhängigkeit von blabla ausgeführt wird, 
Anweisung2 und 3 dagegen immer. Das ist aber nicht Sinn der Sache.

Du zwingst dich damit, immer hinter der if-Abfrage Klammern zu setzen. 
Das ist bei nur einer folgenden Anweisung aber gar nicht notwendig. Das 
funktioniert jetzt, da du es weisst. Damit schiesst du dir aber 
langfristig ins Knie.
Mach es vernünftig!

von Rolf M. (rmagnus)


Lesenswert?

__Son´s B. schrieb:
> Was soll daran "Mist" sein?

Die Erklärung von "Mein grosses Vorbild" hat da noch etwas 
Optimierungspotenzial.

Es ging ihm darum, dass du das Makro nicht genau wie eine Funktion 
behandeln kannst, da es mehrere statements beinhaltet. Dadurch können 
unerwartete Effekte auftreten wie z.B. in:
1
#define X() a(); b()
2
3
if (z == 3) X();

Man erwartet, dass a() und b() nur aufgerufen werden, wenn z den Wert 3 
hat. Tatsächlich wird b() aber immer aufgerufen. Denn durch die 
Makro-Ersetzung entsteht:
1
if (z == 3) a(); b();
oder etwas klarer eingerückt:
1
if (z == 3)
2
    a();
3
b();

Aus dem Grund wird in Makros, die mehrere statements zusammenfassen, 
gerne ein do {} while(0) darum herum geschrieben. Das tut letztendlich 
nichts anderes, als den Code zwischen den Klammern genau einmal 
auszuführen, aber es ist insgesamt wieder ein einzelnes Statement. Damit 
funktioniert die obige Abfrage auch wie erwartet:
1
#define X() do  { a(); b(); } while (0)
2
3
if (z == 3) X();
wird ersetzt durch:
1
if (z == 3)
2
    do
3
    {
4
        a();
5
        b();
6
    } while(0);
Durch den Trick mit dem do/while wird b genau wie a in der Bedingung 
ausgeführt.

: Bearbeitet durch User
von __Son´s B. (bersison)


Lesenswert?

A. K. schrieb:
> wenn du eines Tages mal die {} Klammern weglässt
ahhh! Es ging also nur um meinen Minimal-Auszug;
LED_LOW;
ohne Vor- und Nachstehendes!?
Klar kann das in c nicht einfach nur "dumm" rum stehen...

von Mein grosses V. (vorbild)


Lesenswert?

__Son´s B. schrieb:
> ahhh! Es ging also nur um meinen Minimal-Auszug;

Nein. Es geht darum, dir zu zeigen, wie man vernünftige Makros mit 
mehreren enthaltenen Anweisungen schreibt.

__Son´s B. schrieb:
> Klar kann das in c nicht einfach nur "dumm" rum stehen...

Natürlich kann man das. Aber willst du dir jeden Spezialfall deiner 
Makros merken?

Sinn der Übung ist, daß du gar nicht unbedingt wissen musst, daß das ein 
Makro ist, sondern du dieses genauso wie eine Funktion benutzen kannst 
und benutzen musst. Mit allen Spezialitäten bei der Abfrage von 
Bedingungen oder der Benutzung in Schleifen.

Konsequenterweise kann man das auch so schreiben:
1
#define Makro() do{...}while(0)
2
3
Makro();
4
5
while(1)Makro();
6
7
while(1)
8
{
9
  Makro();
10
}
11
12
if(Bla) Makro(); else {...}
13
14
if(Bla) 
15
{
16
 Makro();
17
} else {...}

Kriegst du die Aufrufe mit deiner Version auch hin? Nein. Bei zwei 
Aufrufen fliegst du auf die Schnauze. Und vor allen Dingen: Weißt du das 
in einem Jahr noch?

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.