www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mehrzeiliges Makro funktioniert nicht


Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

da ich in einem Byte-Stream einzelne Nibble auswerten möchte wollte ich 
dieses Makro schreiben aber leider mag er es nicht!! kann mir jemand 
sagen wo der Fehler zu finden ist?

#define NIBL2NIBL( SOURCEBYTE ,  DESTBYTE )         \
(                                                       \
    ((BYTE)_DESTBYTE_) |=  0x0F                        ;\
    ((BYTE)_DESTBYTE_) ^= ~0x0F                        ;\
    ((BYTE)_DESTBYTE_) |= (SOURCEBYTE & 0x0F)         \
)

Gruß

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu viele Leerzeichen, bei den Parametern dürfen keine sein...
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
(                                                       \
    ((BYTE)_DESTBYTE_) |=  0x0F                        ;\
    ((BYTE)_DESTBYTE_) ^= ~0x0F                        ;\
    ((BYTE)_DESTBYTE_) |= (SOURCEBYTE & 0x0F)         \
)

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke für die schnelle Antwort aber ich bekomme in IAR noch folgende 
Fehlermeldungen. (haben sich auch nicht geändert):

Error[Pe137]: expression must be a modifiable lvalue
Error[Pe018]: expected a ")"
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe065]: expected a ";"

der Code dazu sieht so aus (nur zum testen natürlich):

BYTE a, b;
a = 0xFA;
b = 0xF5;
NIBL2NIBL( a, b );

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da verstehe ich nicht, was Du erreichen willst.
Das Makro macht Unterstriche an die Werte (warum?), und in der letzten 
Makrozeile fehlt das Semikolon.
Willst Du:
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
(                                                       \
    ((BYTE)(DESTBYTE)) |=  0x0F                        ;\
    ((BYTE)(DESTBYTE)) ^= ~0x0F                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
)

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch was:
was soll das Makro denn tun? Momentan sieht es teilweise sinnfrei aus..

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
(                                                       \
    ((BYTE)(DESTBYTE)) |=  0x0F                        ;\
    ((BYTE)(DESTBYTE)) ^= ~0x0F                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
)

1. Zeile: alle Bits in Low-Nibble werden auf 1 gesetzt
2. Zeile: alle Bits werden im Low-Nibble auf 0 gesetzt
3. Zeile: "Kopieren" des SourceLowNibble zum DestLowNibble

die ersten zwei Zeilen sind deswegen nötig um zu garantieren das das 
DestLowNibble wirklich 0 ist und nicht vordefiniert ist, denn da in der 
dritten Zeile ein Veroderung vorgenommen wird ist es möglich das "alte 
Bits" mitgeschleppt werden.

Gruß

Flo

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch zur anderen Antwort...
die unterstrich nur deswegen damit ich garantieren kann das niemand evtl 
eine Variable namens DESTBYTE benutzt deswegen DESTBYTE.

Das Semikolon deswegen nicht damit ich es wie eine normale C-Anweisung 
mit ; abschließen kann (sonst würde ja doppelt ; da stehen)

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum nicht:
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
(                                                       \
    ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
)

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, das mit den Unterstrichen habe ich nicht richtig gesehen, weil Du 
den Code nicht als C-Code eingefügt hattest.....(siehe erster Post...).

[edit] Ohne Semikolon ist o.k., aber dann darf danach keine Klammer 
kommen...

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da man damit da HighNibble auf F setzen würde ich möchte aber das 
High-Nibble unberührt lassen.

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das High Nibble bleibt unberührt, weil es eine UND Verknüpfung 
ist...

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok stimmt ist richtig....

leider kommen immernoch die Fehlermeldungen

Error[Pe137]: expression must be a modifiable lvalue
Error[Pe018]: expected a ")"
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe029]: expected an expression

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

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht '*genau*' dein Makro jetzt aus?
Wie verwendest du es, ebenfalls '*genau*'?

Die Sache mit den Unterstrichen ist Unsinn. Im ganzen
Programm gibt es keine Variable namens DESTBYTE.

Ein Makro macht einfach nur eine Textsubstitution.
Im Source wird der Quelltext

NIBL2NIBL( a, b );

durch den im Makro angegebenen Text ersetzt. Um also die
Fehlermeldungen deuten zu können, muß man den exakten
Text bei der Verwendung des Makros kennen, den exakten
Makrotext und erst dann kann man sich darüber Gedanken machen
welcher neue Text durch die Makrosubstitution entsteht und warum
der Copiler hier Fehler meldet.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ein neues Project gestartet und das ist jetzt alles was drin ist 
mit folgenden Fehlermeldungen....

#define BYTE char
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
(                                                       \
    ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
)

int main()
{
      BYTE a, b;
    a = 0xFE;
    b = 0xFB;
    NIBL2NIBL( a, b );
  return 0;
}

Building configuration: MakroTest - Debug
Updating build tree...
main.c
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe018]: expected a ")"
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe029]: expected an expression

Total number of errors: 4
Total number of warnings: 0

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach mal:
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
    ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Building configuration: MakroTest - Debug
Updating build tree...
main.c
Error[Pe137]: expression must be a modifiable lvalue
Error[Pe137]: expression must be a modifiable lvalue

Total number of errors: 2
Total number of warnings: 0

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

Bewertung
0 lesenswert
nicht lesenswert
Bernhard M. wrote:
> Mach mal:
>
> #define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
>     ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
>     ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)
> 


Kann man machen.
Aber der Fehler besteht darin, dass er ( anstatt { verwendet
hat.
Also: runde Klammern anstatt geschwungenen Klammern.

Das Makro muss lauten
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
{                                                       \
    ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
}

PS: Für einen Datentyp Byte sollte man immer unsigned char
verwenden und nicht einfach nur char. Bei einem char ist
nicht sichergestellt ob der jetzt mit oder ohne Vorzeichen
gewertet wird.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK habs jetzt hinbekommen so funktionierts:

#define NIBL2NIBL(SOURCEBYTE,DESTBYTE){         \
    (DESTBYTE) &=  0xF0                        ;\
    (DESTBYTE) |= ((SOURCEBYTE) & 0x0F);\
}

aber mich würde interessieren warum ich den Cast weglassen muss?

schon mal vielen lieben Dank für eure schnelle Hilfe...

Gruß

Flo

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist auch nicht unbedingt gut....

Dann kriegt man nach Makroauflösung;
{                                                       
    ((BYTE)(b)) &=  0xF0                       ;
    ((BYTE)(b)) |= ((a) & 0x0F)        ;
};
Und nicht alle Compiler mögen das Semikolon an der Stelle (ist es da 
überhaupt erlaubt?).
Deshalb würde ich lieber die Klammern ganz weglassen, da keine lokalen 
Variablen benötigt werden muß man auch keinen Block bilden...

Zweimal editiert, um das Makro richtig aufzulösen ;-)

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Bernhard

habe deinen Vorschlag erst gelesen nachdem ich meinen Post gesetzt 
hab...

leider bringt er aber bei deinem immernoch die Fehlermeldung...

und danke für den Tip mit dem unsigned char

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Ausdruck mit einem typecast ist kein lvalue, genau das besagt
letztlich die Fehlermeldung.  Die linke Seite einer Zuweisung darf
folglich keinen typecast enthalten.

(GCC hat das früher mal toleriert, seit Version 4 aber auch nicht
mehr.)

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann lass den Cast auf BYTE weg, der ist eh nicht richtig sinnvoll...

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt dämmerts mir...

Eigentlich darf mann keine lvalues casten (also kein cast auf der linken 
Seite der Zuweisung), wenns auch einige Compiler erlauben....

Typischerweise ist die Fehlermeldung alles andere als hilfreich...

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK damit ist jetzt alles klar...
also nachmals vielen lieben dank für die superschnelle Problemlösung...

Gruß

Flo

Autor: Michael König (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 1. Zeile: alle Bits in Low-Nibble werden auf 1 gesetzt
> 2. Zeile: alle Bits werden im Low-Nibble auf 0 gesetzt

"Bit-Clear" ist das gleiche wie AND-NOT, aber das hast du später wohl 
auch bemerkt.

> Das Semikolon deswegen nicht damit ich es wie eine normale C-Anweisung
> mit ; abschließen kann (sonst würde ja doppelt ; da stehen)

Im Gegensatz zu manchen anderen Sprachen sind bei C leere Statements 
möglich, d.h. du könntes auch hunderte von Semikolons hintereinander 
haben und der Compiler sollte sich nicht daran stören.

Wie Karl Heinz richtig angemerkt hat, sollte das Makro in einen eigenen 
Block, also in geschweiften Klammern stehen.
Wenn du es in runde Klammern setzt ist es ein Ausdruck und darin sind 
die durch Semikolon abgeschlossenen Statements nicht erlaubt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard M. wrote:

> Typischerweise ist die Fehlermeldung alles andere als hilfreich.

Fand ich gar nicht.  Ich hab's nur durch die Fehlermeldung geschnallt,
was daran foul war.

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

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Bernhard M. wrote:
>
>> Typischerweise ist die Fehlermeldung alles andere als hilfreich.
>
> Fand ich gar nicht.  Ich hab's nur durch die Fehlermeldung geschnallt,
> was daran foul war.

:-)
Muss gestehen: Ich nicht.
Ich hab rumgerätselt warum er denn den lvalue anmeckert. Ein
kurzer Test mit VC++ brachte mich auch nicht weiter.
Als du dann den cast ins Spiel brachtest, viel es wie Schuppen
von den Haaren.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich gebe zu, dass ich durch die kürzlich erfolgte GCC-Änderung in
diesem Bereich das Thema noch einigermaßen im Hinterkopf hatte.
Irgendwo hatten wir auch noch typecasts auf der linken Seite
rumgeistern in hysterischem Code...

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na ja, das mit der Fehlermeldung des Compilers ist so eine Sache...
Ich weiß aus eigener Erfahrung wie schwierig es ist, verständliche 
Fehlermeldungen zu erzeugen, die auch jemanden helfen, der nicht so in 
der Materie (der jew. Applikation) steckt....

Error[Pe137]: expression must be a modifiable lvalue
Error[Pe018]: expected a ")"
Hier kam in der Fehlermeldung doch überhaupt kein Hinweis auf den Cast, 
somit geht der unbedarfte Anwender erst mal davon aus, daß mit dem 
lvalue die Variable gemeint ist (er sagt einem ja nicht, welche 
"expression" er meint)...

Mit die besten Fehlermeldung haben meiner Meinung nach die C++ Compiler 
von HP, da sie seit einigen Jahren auch Hinweise geben, was falsch sein 
könnte.
Z.B. finden sie bei dem typischen Tippfehler im Variablennamen 
üblicherweise die Variable, die man eigentlich gemeint hat, und weisen 
darauf hin.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Problematisch für Fehlermeldungen eines Compilers ist, dass er
den Quelltext ja bereits in einen Syntaxbaum zerlegt hat an dieser
Stelle.  Damit hat er für die linke Seite nur noch einen Ausdruck
mit einem Wert und die Tatsache, dass dieser Ausdruck keinen lvalue
darstellt.  Dass dies wiederum durch den typecast erfolgt war, hat
er u. U. einfach bereits "vergessen" an dieser Stelle.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann auch die linke Seite casten, muß es aber indirekt über einen 
Pointer machen.

Man ist dann aber selbst dafür verantwortlich, daß es sich um Typen im 
gleichen Byteformat handelt.

Also ein char nach int geht nicht.

Aber ein nicht volatile nach volatile oder ein signed nach unsigned 
casten geht.


Peter

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Apropo casten...

was hat das ganze eigentlich mit den Präprozessor casten auf sich?? 
(wenn man das so bezeichnen kann...)

also unterschied zwischen

#define 4

#define 4u

#define 4l

hab noch keine Literatur darüber gefunden (wäre auch für einen Link 
dankbar)

Gruß

Flo

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

Seite 68 (mit der Seitennummer 56).

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.