Portabler Code with signed unsigned in CPP
Du bist hier : | {{#youAreHere:Portabler Code with signed unsigned in CPP}} |
Portablen Code schreiben
Unsigned versus signed
Die integralen Typen (long,int,short,char) in C/C++ können ein Vorzeichen haben oder auch nicht.
Daraus ergeben sich große Unterschiede im Verhalten des Codes auf verschiedenen Architekturen.
Um in der Deklaration den Unterschied abzubilden, kann man die integralen Typen mit signed/unsigned spezifizieren, wobei es für die verschiedenen Architekturen unterschiedliche defaults (signed/unsigend) gibt.
Werden diese Spezifizierer nicht verwendet, wird der Default der Architektur angenommen.
default signed: Windows, Solaris(sparc), Solaris(intel), HP(risc), HP(intel), Linux(intel)
default unsigned : Aix, Linux(s390), Linux(PowerPC)
z.B.
char ist signed char auf einer Intel CPU.
char ist unsigned char auf einer PowerPC Architektur.
Daraus folgt:
char i = -1; if( i < 1 ) -- ist auf einer Intel CPU true if( i < 1 ) -- ist auf einem PowerPC false
Auf dem PowerPC entspricht -1 dem positiven Wert 255.
Lösung:
Will man portablen Code schreiben, muss man immer einen integralen Datentyp genau spezifizieren und sich niemals auf die Defaults der Architektur verlassen.
Der CPP-Header <cstdint> stellt die integralen Datentypen in einer portablen Form, angepasst an die CPU, zur Verfügung. Für portablen Code sollte man ausschließlich die dort definierten Datentypen verwenden.
Also
* aus char wird int8_t * aus unsigned char wird uint8_t * usw.
http://en.cppreference.com/w/cpp/header/cstdint http://www.cplusplus.com/reference/cstdint/
Folgen:
Wird z.B. eine integrale Variable in einer Aufzählung verwendet und der Wertebereich überschritten, kann der Wert negativ werden (default: signed) bzw. werden negative Werte nie erreicht (default:unsigned). Nachfolgende Vergleiche können falsch werden.
Entdeckt man bei einem Code-Review die nicht spezifizierte Deklarationen einer Variable eines integralen Typs, ist davon auszugehen, dass dieser Code nur auf der Architektur korrekt funktioniert, für die die implizite Annahme (signed/unsigned) zutrifft. Solcher Code ist mit den defaults nicht portabel.
Im Compiler gibt es Optionen, die den Default überschreiben. Damit kann man die eigene Schreibweise beibehalten. Besser ist es, gleich die Datetypen aus <cstdint> zu verwenden.
Links:
char type is unsigned with PPC gcc?
http://www.linuxtopia.org/online_books/an_introduction_to_gcc/gccintro_71.html
http://stackoverflow.com/questions/4406447/gccv4-1-2-cross-compiler-integer-promotion-problem