Lassen Sie das folgende Programm test.c
berücksichtigen:Ganze Zahl ohne Vorzeichen Bitfeld Verschiebung Ausbeuten Ganzzahl mit Vorzeichen
#include <stdio.h>
struct test {
unsigned int a:5;
};
int main() {
unsigned int i;
struct test t = {1};
for (i = 0; i < t.a << 1; i++)
printf("%u\n", i);
return 0;
}
Wenn kompilierten mit gcc -Wsign-compare test.c
folgende Warnung erzeugt wird (getestet mit gcc 4.8.1):
test.c:9:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (i = 0; i < t.a << 1; i++)
^
clang -Wsign-compare test.c
erzeugt das Folgende (getestet mit Klang 3.2):
test.c:9:19: warning: comparison of integers of different signs: 'unsigned int' and 'int' [-Wsign-compare]
for (i = 0; i < t.a << 1; i++)
~^~~~~~~~~
1 warning generated.
Somit wird der rechte Operand, ein verschobenes vorzeichenloses Bitfeld, zu einem vorzeichenbehafteten int. Diese Warnung zeigt für jedes Bit Feld Wert zwischen 1 und 31 enthalten. Bei höheren Werten wird keine Warnung ausgegeben. Das ist seltsam.
Dies wurde mit einem Bitfeld vom Typ unsigned short
, unsigned int
und unsigned long
getestet. Letztere zeigen keine Warnung für Bitfeldwerte zwischen 32 und 64 an.
Wenn keine Verschiebung durchgeführt wird, gibt es keine Warnung, daher ist das Bitfeld wie erwartet nicht signiert.
Warum werden Bitfelder mit einer Größe kleiner als 32 Bit beim Verschieben signiert? Ich nehme an, dies ist kein Fehler, da dies sowohl mit gcc
als auch mit clang
übereinstimmt. Ich muss einige Informationen darüber verpassen, wie Bitfelder (oder Verschieben) funktionieren, aber was? Wie kann die Verschiebung eines vorzeichenlosen Werts einen vorzeichenbehafteten Wert ergeben?
Und eine 31-Bit-Ganzzahl ohne Vorzeichen kann als int dargestellt werden und wird daher hochgestuft, aber ein 32-Bit-Vorzeichen ohne Vorzeichen kann nicht hochgestuft werden und bleibt unverändert. Ich wusste nichts von Beförderung. Vielen Dank. – bootleg
@bootleg Wenn ein 32 Bit 'unsigned int' befördert werden kann oder nicht, hängt von der Breite von' unsigned int' ab. Unterschiedliche Ergebnisse für 32 und 64-Bit "unsigned". – chux