Construction type -- common body

Posted by menelaus8888 on Wed, 15 Dec 2021 14:29:37 +0100

Common body

1. Production and significance

Compared with the common body, the biggest feature of the structure is that the members belong to the cooperative relationship. The size of memory space is allocated according to the order in which structure members are defined. However, the common body is different. The members of the common body are the relationship between ourselves and the enemy. Only one member can take effect at a time. Allocate the space size according to the one with the largest memory occupied by the current member.

Structure members can coexist at the same time. (there can be many hobbies)
However, only one member of the community can exist at the same time. (for example, if you want to fill in gender information, you can only fill in male or female)

The background of the common body is related to a historical development period in the past. During this period, the development of hardware can not keep up with the development of software. Therefore, sometimes there is not enough memory space and space needs to be saved, so the data type of common body appears.

2. Type description

union Common body name
{
	Data type member name 1;
	Data type member name 2;
	......	
};

3. Nested definition

A common body nest defines a structure or a common body nest defines a common body.

Many times, we use their storage characteristics to simplify some operations. See the following example program.

4. Define variables, initialization and member references

If we initialize only one of the member variables and use the value of the other member variable, it makes no sense. (because other values are invisible to you and do not take effect)

#include <stdio.h>
#include <stdlib.h>

union test
{
    int i;
    float f;
    double d;
    char ch;
};

int main()
{
    union test a;

    a.f = 3.1415;

    printf("%lf.\n",a.f);

//  Printing the values of unused member variables is meaningless
//  printf("%d.\n",a.i);
    printf("%d\n",sizeof(a));

    return 0;
}

Member reference:

1,Variable name.member name
2,Pointer name->member name

5. Amount of memory used
In the above code, we know that the float data type accounts for 4 bytes in both 32-bit and 64 bit machines. But the community allocates space according to the one with the largest memory occupied by the current member, that is, the double type. So the output is 8.

6. On the problem of function parameter transfer (value transfer, address transfer)

Example:
Now there is a requirement. I have a 32-bit unsigned integer number. I want to know what is the sum of the high 16 bits and the low 16 bits?

Implementation method 1:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main()
{
    uint32_t i = 0x11223344;

    // i> > 16 / / get high order
    // I & 0xFFFF / / get low order

    //Output in hexadecimal
    printf("0x%x.\n",((i >>16) + (i & 0xFFFF)));

    return 0;
}

Use the storage characteristics of structure and common body to simplify some operations. See the following example program.

Implementation method 2: use construction type

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

union
{
    //It's just four bytes
    struct
    {
        //i and j are next to each other
        uint16_t i;
        uint16_t j;
    }x;

    //Consistent with y storage space
    uint32_t y;
}a;

int main()
{
    a.y = 0x11223344;

    //Output in hexadecimal
    //Although y is stored, I can do this
    printf("0x%x.\n",a.x.i+a.x.j);

    return 0;
}

Program run output:

7. Bit domain

There is no practical development significance, but the interview may be successful.

Bit field is a form of using a common body to store variables, but when it stores variables, it may not be in bytes, but in bits.

Let's look at it by way of example.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

union
{
    struct
    {
        //Define a char type A, occupying 1 bit
        char a:1;
        //Define a char type b, occupying 2 bits
        char b:2;
        //I want to use a variable to represent a state.
        //Maybe it has only two states, and I don't have it at all
        //It is necessary to use 8 bits (1 byte) to represent.
    }x;
        //Although it seems to save space, it does not consider the specific hardware platform,
        //The storage modes of different hardware platforms are divided into large end mode and small end mode,
        //In other words, the bit domain is not conducive to transplantation

    char y;
}w;

int main()
{
    w.y = 1;
    
    //Although y is stored, I can do this
    printf("%d.\n",w.x.a);

    return 0;
}

At present, the system adopts the small end mode (the high byte is saved in the high position and the low byte is saved in the low position). What is the printed value at this time?

So why - 1?
Let's analyze the reason.

We use% d to output,% d outputs signed integers.

printf("%d.\n",w.x.a);

We know that numbers in a computer are represented by complements.
The complement is expressed as: the complement of a positive number is itself.
The complement of a negative number is based on its original code, the sign bit remains unchanged, the other bits are reversed, and finally + 1 (i.e. + 1 on the basis of inverse code)

It's a little windy here, but for this problem, a=0 or 1, b=00, 01, 10 or 11 are all values in memory. The values in memory exist in the form of complement, and the highest bit of complement represents both symbol and value.

When a is 0, it represents a positive number, the numerical bit (also the sign bit) is 0, and 0 is output directly.
When a is 1, it indicates a negative number, and the value bit (also the symbol bit) is 1. When outputting, it should be restored to the original code before outputting. How to restore it? The 1 of the value bit is subtracted from 1, and then reversed, and it will still become 1. (because it is a negative number), so the output result is - 1.

Small end mode, the highest (high byte) bit is the symbol bit.

So, and so on.
When in the program

w.y = 2;


Let's use% d to output again. What is the output result?

printf("%d.\n",w.x.b);

When b is 00, the highest bit 0 is the sign bit, indicating a positive number, and the value bit is 00, which directly outputs 0.
When b is 01, the highest bit 0 is the sign bit, indicating a positive number, the value bit is 01, and the output result is 1.

When in the program

w.y = 4;


When b is 10, the highest 1 is the sign bit, so it represents a negative number. It should be restored to the original code before output. How to restore it? If the value bit is 10, first subtract 1 to become 01, and then take the opposite, it will become 10. Because it is negative, the output is - 2

When in the program

w.y = 6;//Or 7:00

That is, when b is 11, the highest 1 is the sign bit, so it represents a negative number. It should be restored to the original code before output. How to restore it? If the value bit is 11, first subtract 1 to become 10, and then take the opposite, it will become 01. Because it is negative, the output is - 1

Topics: C