Hallo,
ich bekomme zwei Bytes die einen int16_t repräsentieren als unsigend
char (high und low.)
Wie bekomme ich die Daten bit-weise (also ohne unsigend to signed
conversation) in den int16_t?
1
int16_tdata;
2
unsignedcharhigh,low;
3
4
....
5
6
// Ohne Cast
7
// 8 bit high nach << = 0?
8
data=low+(high<<8);
9
10
// Mit Cast zu signed
11
// Data korruption durch cast?
12
data=(int16_t)low+((int16_t)high<<8);
13
14
// Mit cast to unsigend
15
// Data korruption durh impliziten cast, unsigend to sigend?
Daniel S. schrieb:> Einentlich brauchst du da nicht casten und persönlich benutze ich da> immer das OR:data = low | (high << 8);
da bin ich mir nicht sicher. Wenn low und high char sind und char signed
ist, kommt da Unsinn raus.
Denn das low wird auf int erweitert und dann ist das höchste bit gesetzt
wenn es low negativ war.
Peter II schrieb:> da bin ich mir nicht sicher. Wenn low und high char sind und char signed> ist, kommt da Unsinn raus.
ok, er hat ja unsigned char geschrieben. dann müsste es gehen.
Peter II schrieb:> conf schrieb:>> Wie bekomme ich die Daten bit-weise (also ohne unsigend to signed>> conversation) in den int16_t?>> im Zweifelsfall so>>
1
>int16_tdata;
2
>unsignedcharhigh,low;
3
>
4
>char*tmp=(char*)&data;
5
>memcpy(tmp,high);
6
>memcpy(tmp+1,low);
7
>
mempcy?? ok vermutlich macht ein kluger compiler alles richtig ich würde
das aber anders machen:
Nils H. schrieb:> mempcy?? ok vermutlich macht ein kluger compiler alles richtig ich würde> das aber anders machen:> uint16_t * tmp = (uint16_t *)&variable;> *tmp++ = low;> *tmp = high;
das kann nicht funktionieren. du meinst vermutlich uint8_t
Nicht schon wieder dieses Thema... Kurzfassung:
Daniel S. schrieb:> immer das OR:data = low | (high << 8);
ist korrekt, falls deine Plattform 2er-Komplement nutzt (tun fast alle).
Peter II schrieb:> im Zweifelsfall so
und
Nils H. schrieb:> Oder gleich ein union nehmen:
Sind "falsch" und plattform-abhängig, funktioniert nur auf Little-Endian
Prozessoren.
Nils H. schrieb:> uint8_t _Byte[2];> uint16_t _Word;
Solche Bezeichner sind verboten und für die Standard-Library reserviert
(alles was __ am Anfang/Ende enthält oder mit _ + Großbuchstabe
beginnt).
conf schrieb:> // Data korruption durh impliziten cast, unsigend to sigend?
Implizite Casts gibt es nicht. Casts sind immer explizit,
Konvertierungen immer implizit.
Dr. Sommer schrieb:>> // Data korruption durh impliziten cast, unsigend to sigend?> Implizite Casts gibt es nicht. Casts sind immer explizit,> Konvertierungen immer implizit.
Hätte ich jetzt als Synonym gesehen.
Worin liegt der Unterschied?
conf schrieb:> ich denke ich werd aufgrund der Lesbarkeit den Union verwenden.
Das ist die schlechteste Begründung überhaupt. Die union ist nicht
portabel und muss zum Endianess der CPU passen. Schön, aber falsch.
Verwende den Shift und gut ist. Das ist lesbar. Bedenke dabei auch, ob
ein int16_t überhaupt der richtige Datentyp ist. Vermutlich ergibt sich
aus den beiden uint8_t-Variablen nur sinnvoll eine uint16_t-Variable,
also eine vorzeichenlose.
Dr. Sommer schrieb:> Sind "falsch" und plattform-abhängig, funktioniert nur auf Little-Endian> Prozessoren.
aber:
1
data=low|(high<<8);
3 Otherwise, the new type is signed and the value cannot be represented
in it; either the result is implementation-defined or an
implementation-defined signal is raised.
Peter II schrieb:> 3 Otherwise, the new type is signed and the value cannot be represented> in it;
Korrekt. Das Ergebnis hängt von der Signed-Darstellung ab. Aber fast
alle Prozessoren nutzen 2er-Komplement, und bei denen ist das Ergebnis
daher gleich. Das könnte man durch etwas Bitfrickelei reparieren, ist
aber immer noch viel besser als memcpy/union/pointer umcasten, denn
LE/BE Probleme treten viel häufiger auf, und das Signed-Problem hat man
da genauso.
Dr. Sommer schrieb:>> 3 Otherwise, the new type is signed and the value cannot be represented>> in it;> Korrekt. Das Ergebnis hängt von der Signed-Darstellung ab. Aber fast> alle Prozessoren nutzen 2er-Komplement, und bei denen ist das Ergebnis> daher gleich.
darum geht es doch nicht. Ein wert von 50000 lässt sich nicht in int16_t
darstellen, damit ist das Ergebnis undefiniert. (auch wenn vermutlich
immer das richtige rauskommt)
Dr. Sommer schrieb:> Solche Bezeichner sind verboten und für die Standard-Library reserviert> (alles was __ am Anfang/Ende enthält oder mit _ + Großbuchstabe> beginnt).
Dann benenne sie um und fertig ist, dein Compiler wird schon meckern,
wenn ihm das nicht gefällt, meine Güte erbsenzählerei hier
Kopfschüttel ...
Peter II schrieb:> Ein wert von 50000 lässt sich nicht in int16_t> darstellen, damit ist das Ergebnis undefiniert. (auch wenn vermutlich> immer das richtige rauskommt)
Ja das sag ich doch... Reden wir aneinander vorbei?
Nils H. schrieb:> Dann benenne sie um und fertig ist
Wäre halt schlau Anfängern korrekte Code-Beispiele zu geben-
Nils H. schrieb:> dein Compiler wird schon meckern
Die meisten Compiler meckern leider nicht. Oft funktioniert es, aber
vielleicht funktioniert es später (neue Compiler/Standard Library
Version) aufgrund einer Überschneidung nicht mehr; vielleicht sogar so
dass der Compiler nicht meckert es aber trotzdem irgendwelche Probleme
gibt.
Nils H. schrieb:> meine Güte erbsenzählerei hier Kopfschüttel ...
Als Programmierer, insb. bei C und C++, muss man Erbsen sehr genau
zählen damit man nicht in eine der unzähligen Fallen gerät...
Die "richtige" Lösung steht ja schon oben. Der Vollständigkeit halber...
conf schrieb:> ich bekomme zwei Bytes die einen int16_t repräsentieren als unsigend> char (high und low.)
Wie wurde denn der ursprüngliche int16_t zu den zwei unsigned char
gemacht!?
Wenn ich das jetzt nochmal zusammenfasse, dann gibt es die richtige
Lösung nicht da entweder
a) die Typekonvertierung nicht definiert ist und ich ggf. ein Problem
mit anderen Compiler (oder Versionen) bekomme.
b) die Union und Pointer von der Endianess der Architektur abhängen,
worunter die Portierbarkeit leidet.
Mikro 7. schrieb:>> Wie wurde denn der ursprüngliche int16_t zu den zwei unsigned char> gemacht!?
Der kommt über eine CAN-Message die ich als ein unsigend char[] bekomme.