为什么代码输出-1代替1

时间:2010-10-27 14:49:14

标签: c

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)p b
$ 7 = {f1 = -1'',f2 = -1''}

如果您需要更多调试命令,请告诉我。请提供执行此操作的命令。

7 个答案:

答案 0 :(得分:8)

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 :(得分:3)

您的位域是一位宽并且是有符号值。最顶部的位通常表示值的符号,因此,将1设置为一位宽的有符号值会设置符号位,以便读取该值会得到-1。

答案 2 :(得分:1)

要添加到Skizz和tristopia的正确答案:对于C99,现代C,位字段应为signedunsigned int类型或bool类型(aka {{ 1}})。某些平台可能允许所有其他类型,但不一定是可移植的。更糟糕的是,即使您将它们指定为普通_Bool,结果也可能是签名或未签名的。因此,如果您只需要一个标记,最好坚持int,当需要多个位时,最好坚持bool

答案 3 :(得分:0)

位域应该通常是'unsigned xxxxx'。

[编辑]
原因就在于你遇到的情况;有人以“不寻常”的方式使用位域,得到他们不应该获得的结果。

位域的要点是反映一点。有点什么价值? 0和1(我只说正常位,我不能理解量子的东西)。 然而,您已经找到了将-1,0,1插入同一个字段的方法。它必须要破坏。我认为很多位域混淆导致负位域,因此无符号修饰符可以减轻这种混乱。

将位域定义为int时,可以使用负值。这就是上述结果的原因 另外,请参阅here以获取有关此主题的更详细信息。请注意,这在SO上已经无数次重复,因此搜索“bitfield unsigned”将证明非常有用。 [/编辑]

To'R。',re:“signness ...是实现定义的,但它不能因元素而异。”

#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

答案 4 :(得分:0)

我相信KevinDTimm是对的 - 位字段通常是unsigned name:x

这就是我认为正在发生的事情:处理器从字段的第一位确定符号。 gcc字符已签名(有unsigned char,因此您的代码实际上是:

struct bit 
{
   char f1;
   char f2;
};

每个字符是一个字节(4位),最上面的字节表示符号(1 = neg,0 = pos)。但是因为你的字段是一位,那就是符号位。你把它设置为负面。

希望这会有所帮助。如果它是错的,请评论,以便我可以解决它。

答案 5 :(得分:0)

上述解释很棒。 为了使您的程序正常工作,1个可能的解决方案可能是使得unsigned int类型的位字段。

答案 6 :(得分:-1)

我不太了解C.例如,我不知道:1char 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

我希望这可以帮到你!