简体   繁体   English

无法理解 C 中的位域

[英]can't understand bit fields in C

For about 3-4 hours and start reading about bit fields in C and I can't understand how they work.大约 3-4 个小时,然后开始阅读 C 中的位域,但我无法理解它们是如何工作的。 For example, I can't understand why the program has the output: -1, 2, -3例如,我不明白为什么程序有输出: -1, 2, -3

#include <stdio.h>

struct REGISTER {
    int bit1 : 1;
    int      : 2;
    int bit3 : 4;
    int bit4 : 4;
};

int main(void) {
    struct REGISTER bit = { 1, 2, 13 };
    printf("%d, %d, %d\n", bit.bit1, bit.bit3, bit.bit4);
    return 0;
}

Can someone give me an explanation?有人可以给我一个解释吗? I tend to think that if I use unsigned in the struct then the output would be positive.我倾向于认为,如果我在结构中使用unsigned ,那么输出将为正。 But I don't know where that -3 comes from.但我不知道-3来自哪里。

Your compiler considers the type int of a bit field as the type signed int.您的编译器将位域的类型 int 视为签名 int 类型。

Consider the binary representation of initializers (it is enough to consider one byte)考虑初始化器的二进制表示(考虑一个字节就足够了)

1  -> 0b00000001
2  -> 0b00000010
13 -> 0b00001101

So the first bit-field having the width equal to 1 gets 1. For an integer with one bit this bit is the sign bit.因此,宽度等于 1 的第一个位字段为 1。对于具有一位的整数,该位是符号位。 So such a bit field can represent two values 0 and -1 (in the 2's complement representation).所以这样的位域可以表示两个值 0 和 -1(在 2 的补码表示中)。

The second initialized bit-field has the width equal to 4. So it stores the bit representation 0010 that is equal to 2.第二个初始化位域的宽度等于 4。因此它存储等于 2 的位表示 0010。

The third initialized bit-field also has the width equal to 4. So its stored bit combination is equal to 1101. The most significant bit is the sign bit and it is set.第三个初始化位域的宽度也等于4。所以它存储的位组合等于1101。最高有效位是符号位,它被设置。 So the bit-field contains a negative number.所以位域包含一个负数。 This number is equal to -3.这个数字等于 -3。

   1101 ( = -3 )
+
   0011 ( = 3 )
   ====
   0000 ( = 0 )

It is implementation-defined whether an int bitfield is signed or unsigned, hence it is actually an error in any program where you care about the value - if you care for the value you will qualify it either as signed or unsigned . int位域是有符号还是无符号是实现定义的,因此在您关心该值的任何程序中,它实际上是一个错误- 如果您关心该值,您会将其限定为signedunsigned

Now, your compiler considers bitfields without specified signedness as signed .现在,您的编译器将没有指定签名的位域视为已签名 Ie int bit4: 4 tells that that bit-field is 4 bits wide and signed .int bit4: 4表示该位域为4 位宽且有符号

13 cannot be represented in a signed 4-bit bitfield as the maximum value is 7 , no matter the representation of negative numbers - 2's complement, 1's complement, sign-and-magnitude. 13 不能在有符号的 4 位位域中表示,因为最大值是7 ,无论负数的表示 - 2 的补码、1 的补码、符号和大小。 An implementation-specified conversion will now occur: in your case the bit representation 1101 is stored as-is in the 2's complement signed bitfield, and it is considered as the 2's complement negative value -3 .现在将发生实现指定的转换:在您的情况下,位表示1101按原样存储在 2 的补码有符号位字段中,并且它被视为 2 的补码负值-3

Same happens for 1-bit signed bitfield: the one bit is the sign bit , hence there are only 2 possible values: 0 and -1 on two's complement systems. 1 位有符号位域也会发生同样的情况:一位是符号位,因此在二进制补码系统上只有 2 个可能的值:0 和 -1。 On one's complement system, or sign-and-magnitude, one-bit bitfield does not make any sense at all because it can only store 0 or a trap value .在补码系统或符号和幅度上,一位位域根本没有任何意义,因为它只能存储 0 或陷阱值

If you want it to be able to store value 13, you will have to use at least 5 bits or use unsigned int: 4 .如果您希望它能够存储值 13,则必须使用至少5位或使用unsigned int: 4

Please Dont use signed int in this operation.请不要在此操作中使用signed int。 here that lead to minus results.这里导致负结果。 if we use unsigned int,The output comes out to be negative如果我们使用 unsigned int,输出结果为负数

What happened behind is that the value 13 was stored in 4 bit signed integer which is equal to 1101. The MSB is a 1, so it's a negative number and you need to calculate the 2's complement of the binary number to get its actual value which is what is done internally.后面发生的事情是值 13 存储在等于 1101 的 4 位有符号整数中。 MSB 是 1,所以它是一个负数,你需要计算二进制数的 2 的补码来得到它的实际值是内部完成的。 By calculating 2's complement you will arrive at the value 0011 which is equivalent to decimal number 3 and since it was a negative number you get a -3.通过计算 2 的补码,您将得到值 0011,它相当于十进制数 3,由于它是一个负数,您将得到 -3。

#include <stdio.h>

struct REGISTER {

  unsigned int bit1: 1;
  unsigned int :2;
  unsigned int bit3: 4;

  unsigned int bit4: 4;
};

int main(void) {
  struct REGISTER bit={1,2,13};
  printf("%d, %d, %d\n", bit.bit1, bit.bit3, bit.bit4);
  return 0;
}

Here the output will be exactly 1,2,13这里的输出正好是 1,2,13

Thanks谢谢

It's pretty easy, you're initializing the bitfields as follows:这很简单,您按如下方式初始化位域:

  1. 1 as bit length 1. That means the MSB is 1, which since the type is int is the sign bit. 1作为位长 1。这意味着 MSB 是 1,因为类型是int是符号位。 So the resulting value is -0-1 = -1.所以结果值是-0-1 = -1。
  2. 2 as bit length 4. MSB (sign bit) is 0, so the result is positive, ie 2. 2作为位长4。MSB(符号位)为0,所以结果为正,即2。
  3. 13 as bit length 4. In binary that is 1101 , so the MSB is 1 (negative), so the resulting value is -2-1 = -3. 13作为位长 4。在二进制中,即1101 ,因此 MSB 为 1(负),因此结果值为 -2-1 = -3。

You can read more about two's complement (the format in which numbers are stored on Intel architectures) here.您可以在此处阅读有关二进制补码(在英特尔架构上存储数字的格式)的更多信息。 The short version is that negative numbers have MSB=1, and to calculate their value you take the negative of their not representation (without the sign bit) minus one.简短的版本是负数的 MSB=1,并且要计算它们的值,您需要将它们的not表示(没有符号位)的负数减去 1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM