Mehrzeiliges Makro funktioniert nicht

Gast #790090
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ß
Gast #790099
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 );
#790103
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:
1
#define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
2
(                                                       \
3
    ((BYTE)(DESTBYTE)) |=  0x0F                        ;\
4
    ((BYTE)(DESTBYTE)) ^= ~0x0F                        ;\
5
    ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)        ;\
6
)
Gast #790122
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
Gast #790125
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)
Gast #790134
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
#790141
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.
Gast #790145
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
Gast #790150
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
#790151
Lesenswert?

Bernhard M. wrote:
> Mach mal:
>
1
> #define NIBL2NIBL(SOURCEBYTE,DESTBYTE)         \
2
>     ((BYTE)(DESTBYTE)) &=  0xF0                        ;\
3
>     ((BYTE)(DESTBYTE)) |= ((SOURCEBYTE) & 0x0F)
4
>


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

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

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.
Gast #790156
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
#790157
Lesenswert?

Ist auch nicht unbedingt gut....

Dann kriegt man nach Makroauflösung;
1
{                                                       
2
    ((BYTE)(b)) &=  0xF0                       ;
3
    ((BYTE)(b)) |= ((a) & 0x0F)        ;
4
};
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 ;-)
Gast #790171
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.
#790220
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.
#790236
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.
Moderator Persönliche Seite #790247
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.
#790253
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
Gast #790384
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

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