讓考慮以下程序test.c
:無符號整數位字段移產量符號整數
#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;
}
當與gcc -Wsign-compare test.c
編譯以下警告產生(用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
產生以下結果(用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.
因此,右操作數即移位的無符號位域成爲帶符號的整數。此警告顯示包含1到31之間的任何位字段值。對於更高的值,不會產生警告。這很奇怪。
這用unsigned short
,unsigned int
和unsigned long
類型的位字段進行了測試。後者不包含32和64之間的位字段值的任何警告。
當沒有移位完成沒有警告,因此位字段未按預期簽名。
爲什麼比特位大小低於32位的字段在移位時被簽名?我認爲這不是一個錯誤,因爲這與gcc
和clang
一致。我必須錯過一些關於位域(或位移)如何工作的信息,但是什麼?如何移動無符號值產生一個有符號值?
而一個31位無符號整數可以表示爲一個int,因此被提升,但是一個32位無符號整數無法被提升並保持不變。我不知道升職。謝謝。 – bootleg
@bootleg如果32位'unsigned int'可以或不可以被提升,則取決於'unsigned int'的寬度。 32位和64位「無符號」的結果不同。 – chux