2017-07-18 1 views
0

Ein Datenbyte wird in einer Mitgliedsvariablen 'char' gespeichert. Es sollte wahrscheinlich als "unsigned char" gespeichert werden, aber das kann nicht geändert werden. Ich muss es durch eine 'int' Variable abrufen, aber ohne das Vorzeichen Bit zu verbreiten.Konvertierung von char in int ohne Vorzeichen für die Bitweiterleitung in C++

Meine Lösung war (UINT und UCHAR sind die offensichtlichen Typen):

void Foo::get_data(int *val) 
{ 
    if(val) 
     *val = (int)(UINT)(UCHAR)m_data; // 'm_data' is type 'char' 
} 

dies die beste Lösung für mich zu sein schien. Ich könnte anstelle des Castings

*val = 0xff & (int)m_data; 

verwenden, aber das scheint nicht so lesbar. Welche Alternative ist besser, wenn auch und warum?

+4

Sie haben am häufigsten (und wohl offensichtlichsten) weggelassen: einfach in 'unsigned char' umwandeln und das Ergebnis direkt in Ihrem' int' speichern. – WhozCraig

+0

@WhozCraig: Ah, tatsächlich - das ist ansprechend. +1. In Antwort konvertieren und ich werde akzeptieren. – MPW

+1

Warum nicht einfach abs() benutzen? Es ist definitiv der sauberste Weg, es zu tun. Es wird auch wahrscheinlich auf die effizienteste Weise möglich gemacht, wenn Sie einen guten Compiler verwenden. – patatahooligan

Antwort

2

Schreiben Sie einfach

*val = (UCHAR)m_data; 

Wie nun der Ausdruck (UCHAR)m_data ein Typ ohne Vorzeichen hat, wird weder Vorzeichenbit vermehrt werden.

1

Die Besetzung ist besser, weil einige Compiler (zB. Clang) tatsächlich extra Code für die bitweise und erzeugen. Natürlich brauchen Sie nur die eine Besetzung zu unsigned char.

Die Besetzung drückt auch Ihre Absicht besser aus: Die Daten sind eigentlich ein Zeichen ohne Vorzeichen, das Sie zu einem int verschieben. Also würde ich es sogar mit Compilern, die den gleichen Code erzeugen, besser bezeichnen.

1

Die Art der Umwandlung ist hier Integral promotion.

Bei der Heraufstufung auf einen breiteren Integer-Typ wird der Wert immer mit seiner Signedness "erweitert", sodass das Vorzeichen an die neuen höherwertigen Bits für vorzeichenbehaftete Werte weitergegeben wird. Um die Zeichenausbreitung zu vermeiden, konvertieren Sie zuerst einen vorzeichenbehafteten Wert in den entsprechenden vorzeichenlosen Typ.

Sie können dies mit einer expliziten *val = static_cast<UCHAR>(m_data) tun.


Oder sicherer, mit as_unsigned Funktion als *val = as_unsigned(m_data). Funktion as_unsigned wie folgt aussieht:

inline unsigned char as_unsigned(char a) { return a; } 
inline unsigned char as_unsigned(unsigned char a) { return a; } 
inline unsigned char as_unsigned(signed char a) { return a; } 
// And so on for the rest of integer types. 

Mit as_unsigned das Risiko dieser expliziten Umwandlung eliminiert nach der Wartung falsch werden, sollte m_data eine größere ganze Zahl wird sie ein weitere Überlastung von as_unsigned automatisch, ohne dass der Betreuer manuell den Ausdruck verwenden zu aktualisieren. Die Umkehrfunktion as_signed ist ebenfalls nützlich.

Verwandte Themen