Bit field structure Introduction

Recent practice come into contact with a new knowledge point, the bit field structure C / C ++ is.

The following excerpt from the beginning: here Wallpaper

Bit field (bit-field) is a space-member variable defined in units of the structure (or union) in the share. Structure (FLC) bit field containing a bit field structure is referred to. Bit segment structure using only space-saving, and convenient in operation.

Bit segment is defined format:

1
type [was]: Digits

Which is the only type int, unsigned int, signed int three types (int type can represent negative depending on the compiler may be, such as int in VC acquiescence is signed int, can represent a negative number). Var bit segment name is an optional parameter, i.e., may be omitted. digits represent the binary digits of this bit segment share.

For example, you can define a bitfield structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// sizeof(A): 4
struct A
{
  uint32_t a: 12;
  uint32_t b: 10;
  uint32_t c: 10;
};

// sizeof(B): 12
struct B
{
  uint32_t a;
  uint32_t b;
  uint32_t c;
};

uint32_tActually unsigned intan alias, and specifies four bytes of data stored in an int, and 1byte = 8bits, 4 bytes Total 32bits, structure A bitfield used to specify each member occupies bit number. Can be seen, the number of bits in A three members occupy a total of 32, that is, 4 bytes. Therefore the structure A is the space occupied by 4 bytes, whereas B does not use bit field, the three members are each four bytes, a total of 12 bytes. Plainly, the bit field is a member of a more compact structure on the bit arrangement, less space.

The following excerpt open period:

About bitfield structure The following points are the following :( "segment bit is bit field", cf ref1 )

  1. Type bit segment can only be int, unsigned int, signed int three types, or type can not float char;
  2. Bit segment representing the number of bits can not exceed the maximum number of bits that can represent basic types, such as the VC int is 4 bytes, it is at most 32;
  3. Unnamed bit segment can not be accessed, but will occupy space;
  4. Can not be address-bit segment operation;
  5. If bit segment representing the number of bits is 0, then this bit segment must be unknown bit field, the next bit from the next segment bit memory cell section (here bit memory cell section 4 bytes tested in VC environment ) begin to store;
  6. If the bit segments appear in an expression, it will automatically update integer automatically converted to an int or unsigned int.
  7. When the position of the segment assignment, it is best not to exceed the maximum range of a bit segment can be represented, as this may cause unexpected results.
  8. Bit segment of an array can not appear.

For bit segment structure, the compiler will automatically optimize storage space, there are several of these principles:

  1. If a bit segment memory cell can store all the members have a bit segment structure, then all members of the bits in the segment can be placed only a configuration bit memory cell section, the two bit segments can not be placed in the storage unit; if a bit segment storage means can not accommodate all the members of the lower section of the structure, then the remaining bits from the stored starting from the next segment bit memory cell section. (VC bit segment in memory cell size is 4 bytes).
  2. If a bit segment structure occupies only a 0 bit unknown segment, only 1 or 0 bytes of space (C language is accounted for 0 bytes, and C ++, accounting for 1 byte); otherwise, in any other case , the space occupied by the structure of a bit field at least a bit size segment of memory cells;

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    
    #include <iostream>
    
    using namespace std;
    
    // sizeof(A): 4
    struct A {
    uint32_t a: 4;
    uint32_t b: 3;
    uint32_t c: 1;
    };
    
    // sizeof(B): 12
    struct B {
    uint32_t a;
    uint32_t b;
    uint32_t c;
    };
    
    // sizeof(C): 8
    struct C {
    uint32_t a: 1;
    uint32_t : 0;
    uint32_t c: 2;  // 不会和a凑在一起,新开一个字节存
    };
    
    // sizeof(D): 12
    struct D {
    uint32_t a: 1;
    uint32_t: 0;    / 大专栏  位域结构体简介/ 隔断
    uint32_t: 6;    // 开启新的位域存储单元
    uint32_t d: 32; // 前一个位域不够放,开启新的存放单元
    };
    
    // sizeof(E): 4
    // 内存分布简图
    // 0000 0000 0000 0000
    // a--- b--- cd-------
    struct E {
    uint32_t a: 1;
    char b;        // 隔断
    uint32_t c: 1; // 在下一个存储单元
    uint32_t d: 15; // 四个成员刚好占用32bits,即4个字节
    };
    
    template <typename T>
    void Print(const T&)
    {
    std::cout << sizeof(T) << std::endl;
    }
    
    // test
    int main()
    {
    A a;
    B b;
    C c;
    D d;
    E e;
    Print(a); // 4
    Print(b); // 12
    Print(c); // 8
    Print(d); // 12
    Print(e); // 4
    return 0;
    }
    

Use the following tests:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <cstdio>

using namespace std;

// sizeof: 4
struct TcpMsgHead {
  uint32_t length: 16;
  uint32_t flags: 8;
  int      num: 8;
};

void Print(const TcpMsgHead& msg)
{
  printf("length: %8dn", msg.length);
  printf("flags:  %8dn", msg.flags);
  printf("num:    %8dn", msg.num);
}

// test
int main()
{
  TcpMsgHead head;
  head.length = 0xffff; // 2^16 - 1 = 65535
  head.flags = 0xff;    // 2^8 - 1 = 255
  head.num = 0xff;
  Print(head);
  return 0;
}

The output of the program is:

1
2
3
length:    65535
flags:       255
num:          -1

Explain why num members -1:
First num set to 8 bits, and the num of type int, is signed. For signed integers, an internal computer's complement representation.
0xff into binary
1111 1111
This is precisely the complement of -1.

其实,Ycm给出的提示已经很明确了:
tr1
Ycm提示这里发生了隐式截断。255被截断成了-1. 如果换成 0x11 也就是二进制的 0001 0001, 则不会发生截断,因为8比特足够描述0x11,符号位是0,表示正数,所以这很符合我们的预期。但是如果再加一个2呢?
tr2
可以看到Ycm提示发生截断,
529被截断成了17, 即
0010 0001 0001 被截断成了 0001 0001
也就是说,我结构体定义的时候已经确定了num只有8比特位可以存。高于8比特的数据全都截断。如果最高位是1,则会被转成负数,这可能和你的预期不符。所以一定不要设置超过容量的数据。

Reference

  1. 浅谈C语言中的位段


Guess you like

Origin www.cnblogs.com/liuzhongrong/p/11874888.html