位域的概念

4
struct A
{
 int a:2;
 int b:3;
 int c:3;
};

int main()
{
 struct A p = {2,6,1};
 printf("\n%d\n%d\n%d\n",p.a,p.b,p.c);
 return 0;
}    

输出结果为:-2,-2,1。

在C编译器和C++编译器中,上述代码的输出结果是什么?为什么?


为什么呢,这是有符号整数和无符号整数之间的区别。你可能想要使用unsigned - Nate
@WilliamPursell,对于有符号的值,位域是完全定义明确的。 - Carl Norum
可能它正在使用有符号循环规则。就像当我们给char类型的变量输入超出其范围的值时一样。 - suraj.prasoon
可能它正在使用有符号循环规则。当我们给char类型的变量赋值超出其范围时,就会出现这种情况。例如:如果我们将128作为输入值赋给char a,然后打印'a'的值,它将打印-128,即char类型的范围循环在-128到127之间。类似地,如果我们输入130,则输出将为-126。 - suraj.prasoon
如果是这样的话,那么6就不应该被正确解释为-2了,对吧? - Dharini Chandrasekaran
显示剩余3条评论
4个回答

5
你的系统似乎正在使用二进制补码。一个持有22位位域将在二进制中为10,这在二进制补码系统中是-2。同样,110(6)对于3位补码表示来说是-2。而1则是普通的1

同时阅读关于带符号位域的这里


3
我使用C编译器得到了-2 -2 1。问题在于您的位域对您要存储的数字来说太小了。在前两种情况下,最左边的位是1,所以它们被解释为负数。要解决这个问题,可以选择以下方式之一:
  1. 使您的位域更大
  2. 将您的位域声明为无符号整数而不是整数
  3. 在打印之前强制转换为无符号整数并使用%u进行打印。

1
你之所以得到那些答案,是因为这个程序的原因:
#include <stdio.h>
#include <stdint.h>

int main(void)
{
    int32_t a = 4294967294;
    printf("%d\n", a);
    return 0;
}

输出结果为-2。用一个过大的数字初始化有符号变量会导致其被解释成不同的值。根据规范:

否则,新类型是有符号的,而该值无法在其中表示;结果要么是实现定义的,要么是引发实现定义的信号。


1

现在让我们看看到底发生了什么。让我们从给定的代码开始:

struct A
{
 int a:3;
};
int main()
{
 struct A p = {5};
 printf("%d",p.a);
}

在3位中,由于这3位设置的符号位是1,因此值为101(5),因此我们需要找到101的二进制补码,即011(3)。 因此,应用上述逻辑,我们的输出将为-3。其他类似地可证明。

例如,对于1001(9),由于a:3,我们将采取3位数值,因此它将是001(1)。由于这里符号位未设置,即为1,因此不需要使用2的补码。答案直接为1。 其他情况类似。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接