Union and bit-field are introduced from isa underlying structure

We briefly introduced the underlying data structure of ISA in the isa underlying structure analysis

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};
Copy the code

Through the above source code found that isa_t isa union (union/union), union means common memory, that is, isa still occupies a total of 8 bytes of memory, a total of 64 binary bits. Where ISA_BITFIELD macro definitions are expressed in different architectures as follows:

# if __arm64__
#   define ISA_BITFIELD                                                      \
      uintptr_t nonpointer        : 1;                                       \
      uintptr_t has_assoc         : 1;                                       \
      uintptr_t has_cxx_dtor      : 1;                                       \
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
      uintptr_t magic             : 6;                                       \
      uintptr_t weakly_referenced : 1;                                       \
      uintptr_t deallocating      : 1;                                       \
      uintptr_t has_sidetable_rc  : 1;                                       \
      uintptr_t extra_rc          : 19
# elif __x86_64__
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
Copy the code
  • Because of the nature of the union,cls , bitsAs well asstructAre all8Byte memory, which means they are completely overlapping in memory.
  • In fact,runtimeIn, any pairstructAnd get certain values, such asextra_rcIn fact, it’s all done by rightbitsDo bit operations to achieve.
  • bitsstructCan be seen as:bitsProvides operations externallystructInterface, whilestructThat tells youbitsThe definition of each binary bit in.

Next, let’s delve into union and bitfield.

A consortium

  • The difference between a structure and a Commons is that the members of a structure occupy different memory and have no effect on each other. However, all members of the community occupy the same memory segment, and modifying one member affects all other members.
  • The memory used by the structure is greater than or equal to the sum of the memory used by all the members (there may be gaps between the members), and the memory used by the common is equal to the memory used by the longest member. The pool uses a memory override technique, in which only one member’s value can be held at a time. If a new member is assigned a value, the value of the original member will be overwritten.
// union {char bits; Struct {// 0000 1111 char front: 1; char back : 1; char left : 1; char right : 1; }; } _direction;Copy the code
  1. Multiple members can be defined in a union, and the size of the union is determined by the largest member size
  2. Members of a consortium share a single memory and can only use one member at a time
  3. Assigning a value to one member overwrites the values of other members
  4. Storage efficiency is higher, more readable, can improve the readability of code, you can use bit operation to improve the storage efficiency of data

A domain

In addition to defining basic data types, bitfields can also be used to build data members, which means that a data member may occupy only a few bits of storage space in the structure. The main purpose of defining bitfields in a structure is to save memory space. Suppose a structure has eight data members of type BOOL that describe eight states. So we need to define 8 BOOL data members, so that the structure instance occupies 8 bytes of memory, which could be expressed in 1 byte of memory if we used the bitfield definition. The format for defining bitfields is as follows:

Struct {// bit domain: char front: 1; char back : 1; char left : 1; char right : 1; };Copy the code
  1. A member of a bit structure can be defined asunsigned, can also be defined assignedOr is itchar, but when the member length is1Is considered to beunsignedType. Because a single bit can’t have a sign.
  2. Arrays and Pointers cannot be used as members of a bit-structure, but bit-structure variables can be arrays and Pointers. If they are Pointers, their members are accessed the same way as Pointers.
  3. The total length of the bit structure (bits), the sum of the bits defined by each bit member (if of the same type)
  4. Bit-structure members can be used with other structure members.
    • Since bitfields are not allowed to span two bytes, the length of a bitfield cannot be greater than the length of one byte, that is, cannot exceed8Bit binary.
    • A bit-field can have no bit-domain name, which is used only for padding or repositioning. Nameless bit fields are not available.
    • If adjacent bit-field fields are of the same type and the sum of their bitwidths is less than that of the typesizeofSize, the following field will be stored next to the preceding one until it can no longer accommodate it.
#include <stdio.h> struct test { char a : 2; char b : 3; char c : 1; }; struct test1 { char a : 2; char b : 3; char c : 7; }; struct { short int a:2; int b:4; char c; }test2; struct { int a:2; int b:4; char c; }test3; struct { short s1:3; short s2:3; short s3:3; }test4; struct{ char c1:3; char c2:2; char c3:2; }test5; struct test6 { int a:4; int b:3; char c; }; int main(int argc, const char * argv[]) { // insert code here... Printf ("test length :%d\ntest1 Length :%d\ntest2 Length :%d\ntest3 Length :%d\ntest4 Length :%d\ntest6 length :%d\n",sizeof(struct test),sizeof(struct test1),sizeof(test2),sizeof(test3),sizeof(test4),sizeof(test5),sizeof(struct test6)); return 0; }Copy the code
Console output: test Length :1 test1 Length :2 test2 Length :4 test3 Length :4 test4 Length :2 test5 Length :1 test6 length :4 Program ended with exit code: 0Copy the code
Quiz:

In 32-bit environment, given structure

Struct A
{
    Char t:4;

    Char k:4;

    Unsigned short i:8;

    Unsigned long m;
};
Copy the code

qSizeof (A)= _____;

A. 6 B. 7 C. 8 D

The variable is followed by: and then a number is added to indicate the bitfield, which means that the variable is stored in bits, not bytes. This is a way that computers save space. Char is one byte (8 bits), so t and k add up to exactly 8 bits, or one byte. And then the short has 8 of the 16 bits, and there's not enough space left for the long, so it counts as 2 bytes. Since long is 4 bytes at 32, 1 +2 +4 = 7. And then I align the structures, so it's 8.