Knowledge of the C language about unions

  • 2020-09-16 07:43:28
  • OfStack

When multiple data require Shared memory or when multiple data fetch only 1 at a time, you can take advantage of the union (union). In C Programming Language 1, the commonwealth is described as follows:

1) Consortium is a structure;

2) All its members have an offset of 0 relative to the base address;

3) The structure space should be large enough to accommodate the widest members;

4) Its alignment should fit all the members;

Explain the four descriptions below:

Since all members of the union share 1 segment of memory, the offset of the first address of each member to the base address of the union variable is 0, that is, the first address of all members is 1. In order for all members to share 1 segment of memory, the space must be large enough to accommodate the widest of these members. For the sentence "alignment to fit all members" means that it must fit all members' own alignment.

Here are some examples:

As a consortium


union U
{
 char s[9];
 int n;
 double d;
};

s takes up 9 bytes, n 4 bytes, and d 8 bytes, so it needs at least 9 bytes of space. The actual size, however, is not 9, but 16 as measured by the operator sizeof. This is because there is a byte alignment problem and 9 is not divisible by either 4 or 8. So complement the byte to 16, which corresponds to the alignment of all members themselves. It can be seen from this that the space occupied by the union is not only dependent on the widest member, but also related to all members, that is, its size must meet two conditions:

1) The size is large enough to accommodate the widest member;

2) The size is divisible by the size of all the basic data types it contains.

Test procedure:


/* Test complex  2011.10.3*/

#include <iostream>
using namespace std;

union U1
{
 char s[9];
 int n;
 double d;
};

union U2
{
 char s[5];
 int n;
 double d;
};

int main(int argc, char *argv[])
{
 U1 u1;
 U2 u2;
 printf("%d\n",sizeof(u1));
 printf("%d\n",sizeof(u2));
 printf("0x%x\n",&u1);
 printf("0x%x\n",&u1.s);
 printf("0x%x\n",&u1.n);
 printf("0x%x\n",&u1.d);
 u1.n=1;
 printf("%d\n",u1.s[0]);
 printf("%lf\n",u1.d);
 unsigned char *p=(unsigned char *)&u1;
 printf("%d\n",*p);
 printf("%d\n",*(p+1));
 printf("%d\n",*(p+2));
 printf("%d\n",*(p+3));
 printf("%d\n",*(p+4));
 printf("%d\n",*(p+5));
 printf("%d\n",*(p+6));
 printf("%d\n",*(p+7));
 return 0;
}

The output result is:

[

16
8
0x22ff60
0x22ff60
0x22ff60
0x22ff60
1
0.000000
1
0
0
0
48
204
64
0

]

For sizeof (u1) = 16. Since s in u1 accounts for 9 bytes, n for 4 bytes, and d for 8 bytes, a minimum of 9 bytes is required. The basic data types are char, int and double, which occupy 1,4,8 bytes respectively. In order to make the space occupied by u1 divisible by 1,4,8, the bytes need to be filled up to 16, so sizeof(u1)=16.

For sizeof (u2) = 8. Since s in u2 accounts for 5 bytes, n for 4 bytes, and d for 8 bytes, a minimum of 8 bytes is required. The basic data types it contains are char, int and double, which occupy 1, 4, and 8 bytes respectively. In order to make the space occupied by u2 divisible by 1, 4, and 8, there is no need to fill the bytes, because 8 itself can meet the requirements. Thus sizeof (u2) = 8.

As you can see from the base address of each member printed, the base address of each member in the union is the same, equal to the starting address of the union variable.

For u1.n =1, assign n of u1 to 1, then the data stored in the first 4 bytes of the memory segment is 00000001 00000000000000000000000000

Therefore, taking the data of s[0] represents taking the data of the first unit, whose integer value is 1, so the printed result is 1.

As for the printed d of 0.000000 would like as follows. Given that the data stored in the first 4 bytes of memory in this segment is 00000001 00000000 00000000 00000000, print the result 48,204,64,0 above to know that the data in the next 4 bytes of memory is 00110000 11001100 0100000000000, so it represents a 2 base floating point number of 0

00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001

For double data, the 63rd bit 0 is the symbol bit, 62-52 00000000100 is the order code, 0000 11001100 00110000 0000000000000000001 is the mantissa, the mantissa is about 0 according to its value, and the order code is 4-1023=-1019, so it represents a floating point number of 1.0*2^(-1019)=0.00000000000...... , so the output result is 0.000000.

That's all for C. For more information on C, check out the other articles on this site!


Related articles: