[英]why does the code output -1 in place of 1
int main ()
{
struct bit{
char f1:1;
char f2:1;
};
struct bit b;
b.f1= 0x1;
b.f2 = 0x1;
printf("%d\n",b.f1);
return 0;
}
使用gcc編譯代碼輸出-1。 它應該不是1嗎? 是因為我正在編譯一個小端機器嗎?
補充:使用GDB進行調試時,我看到初始化struct成員后的值為-1。 即打印前它是-1。 以下是GDB的打印輸出:
(gdb)pb
$ 7 = {f1 = -1'',f2 = -1''}
如果您需要更多調試命令,請告訴我。 請提供執行此操作的命令。
char
可以是unsigned
或者可以是signed
類型,由編譯器來決定。 在你的情況下,它顯然是signed
所以當你打印你的位字段時,編譯器會將符號擴展到你的位擴展到的int
的大小。 在2補碼表示中,不應忘記-1表示為每個位集11111111 11111111 11111111 11111111在32位int上為-1。 如果只有1位,則只能表示2個補碼中的2個值:0和1,它是0和-1的二進制表示。
編輯:這里是C標准第6.2.5節第15節的實際部分:char,signed char和unsigned char這三種類型統稱為字符類型。 實現應將char定義為具有與signed char或unsigned char.35相同的范圍,表示和行為
35)在limits.h中定義的CHAR_MIN將具有值0或SCHAR_MIN之一,這可用於區分這兩個選項。 無論做出何種選擇,char都是與其他兩種類型不同的類型,並且與兩者都不兼容。
您的位域是一位寬並且是有符號值。 最頂部的位通常表示值的符號,因此,將1設置為一位寬的有符號值會設置符號位,以便讀取該值會得到-1。
要添加到Skizz和tristopia的正確答案:對於C99,現代C,位字段應為signed
或unsigned int
類型或bool
類型(aka _Bool
)。 某些平台可能允許所有其他類型,但不一定是可移植的。 更糟糕的是,即使您將它們指定為plain int
,結果也可能是有符號或無符號的。 因此,如果你只需要一個標志,那么最好堅持使用bool
,當你需要多個位時,可以選擇unsigned
。
位域通常
應該是
'unsigned xxxxx'。
[編輯]
原因就在於你遇到的情況; 有人以“不尋常”的方式使用位域,得到他們不應該獲得的結果。
位域的要點是反映一點。 有點什么價值? 0和1(我只說正常位,我不能理解量子的東西)。
然而,您已經找到了將-1,0,1插入同一個字段的方法。
在某個地方,它必須打破。
我相信很多位域混淆會導致負位域,因此無符號修飾符可以減輕這種混亂。
將位域定義為int時,可以使用負值。 這就是上述結果的原因。
此外,請參閱此處以獲取有關此主題的更詳細信息。 請注意,這已經在SO上進行了無數次重復,因此搜索“bitfield unsigned”將證明非常有啟發性
[/編輯]
對於'R.',re:“簽名......是實現定義的,但它不能因元素而異。”
#include <stdio.h>
int main ()
{
struct bit{
char f1:1;
unsigned char f2:1;
};
struct bit b;
b.f1 = 1;
b.f2 = 1;
printf("%d\n",b.f1);
printf("%d\n",b.f2);
return 0;
}
產生,作為輸出:
-1
1
我相信KevinDTimm是正確的 - 位字段通常是unsigned name:x
。
這就是我認為正在發生的事情:處理器從字段的第一位確定符號。 gcc字符已簽名(有一個unsigned char
,所以你的代碼實際上是:
struct bit
{
char f1;
char f2;
};
每個字符是一個字節(4位),最上面的字節表示符號(1 = neg,0 = pos)。 但是因為你的字段是一位,那就是符號位。 你把它設置為負面。
希望這可以幫助。 如果它是錯的,請評論,以便我可以解決它。
以上解釋很棒。 為了使您的程序正常工作,1個可能的解決方案可能是使得unsigned int類型的位字段。
我不太了解C. 例如,我不知道:1
在char f1:1
做了什么,但我能夠通過刪除以下代碼來使我的PC上運行此代碼:
#include <stdio.h>
int main ()
{
struct bit{
char f1;
char f2;
};
struct bit b;
b.f1 = 0x1;
b.f2 = 0x1;
printf("%d\n",b.f1);
return 0;
}
輸出如下:
chooper@brooklyn:~/test$ gcc -o foo foo.c
chooper@brooklyn:~/test$ ./foo
1
我希望這可以幫助你!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.