Ich verwende unsignierte Ints, um meinen Code und seine Absichten klarer zu machen. Zum Schutz vor unerwarteten impliziten Konvertierungen beim Rechnen mit vorzeichenbehafteten und vorzeichenlosen Typen verwende ich eine vorzeichenlose Kurzform (normalerweise 2 Byte) für meine vorzeichenlosen Variablen. Dies ist aus mehreren Gründen effektiv:
- Wenn Sie mit Ihren vorzeichenlosen Kurzvariablen und Literalen (die vom Typ int sind) oder Variablen vom Typ int arithmetisch arbeiten, wird sichergestellt, dass die vorzeichenlose Variable vor der Auswertung des Ausdrucks immer zu einem int hochgestuft wird, da int immer einen höheren Rang als short hat . Dies vermeidet unerwartetes Verhalten beim Rechnen mit vorzeichenbehafteten und vorzeichenlosen Typen, vorausgesetzt, das Ergebnis des Ausdrucks passt natürlich in ein vorzeichenbehaftetes int.
- In den meisten Fällen überschreiten die von Ihnen verwendeten vorzeichenlosen Variablen nicht den Maximalwert eines vorzeichenlosen 2-Byte-Kurzschlusses (65.535).
Das allgemeine Prinzip ist, dass der Typ Ihrer vorzeichenlosen Variablen einen niedrigeren Rang haben sollte als der Typ der vorzeichenbehafteten Variablen, um die Heraufstufung zum vorzeichenbehafteten Typ sicherzustellen. Dann haben Sie kein unerwartetes Überlaufverhalten. Natürlich können Sie dies nicht immer sicherstellen, aber (meistens) ist es möglich, dies sicherzustellen.
Zum Beispiel hatte ich kürzlich eine for-Schleife, die ungefähr so aussah:
const unsigned short cuint = 5;
for(unsigned short i=0; i<10; ++i)
{
if((i-2)%cuint == 0)
{
//Do something
}
}
Das Literal '2' ist vom Typ int. Wenn i ein vorzeichenloses int anstelle eines vorzeichenlosen short wäre, würde in dem Unterausdruck (i-2) 2 zu einem vorzeichenlosen int heraufgestuft (da vorzeichenloses int eine höhere Priorität als vorzeichenloses int hat). Wenn i = 0 ist, ist der Unterausdruck gleich (0u-2u) = ein massiver Wert aufgrund eines Überlaufs. Dieselbe Idee mit i = 1. Da i jedoch ein Short ohne Vorzeichen ist, wird es auf den gleichen Typ wie Literal '2' hochgestuft, das mit int signiert ist, und alles funktioniert einwandfrei.
Für zusätzliche Sicherheit: In dem seltenen Fall, dass die Architektur, auf der Sie implementieren, int auf 2 Byte erhöht, werden möglicherweise beide Operanden im arithmetischen Ausdruck in unsigned int hochgestuft, wenn die unsigned short-Variable nicht passt in das vorzeichenbehaftete 2-Byte-int, dessen letzterer einen Maximalwert von 32.767 <65.535 hat. ( Weitere Informationen finden Sie unter https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned .) Um sich davor zu schützen, können Sie Ihrem Programm einfach einen static_assert wie folgt hinzufügen:
static_assert(sizeof(int) == 4, "int must be 4 bytes");
und es wird nicht auf Architekturen kompiliert, bei denen int 2 Bytes beträgt.
for(unsigned int n = 10; n >= 0; n --)
(Endlosschleifen)