[C Advanced] bit segment - enumeration - Union

catalogue

1. Bit segment

      1.1. What is a bit segment

      1.2. Memory allocation of bit segment

      1.3 cross platform problem of location section

      1.4 application of bit segment

2. Enumeration

      2.1 definition of enumeration type

      2.2 advantages of enumeration

      2.3 use of enumeration

3. United

      3.1 definition of association type

      3.2 characteristics of joint

      3.3 calculation of joint size

1. Bit segment

1.1. What is a bit segment

  • The declaration and structure of bit segments are similar, with two differences:
  1. The member of a bit field must be int, unsigned int, or signed int.
  2. The member name of the bit field is followed by a colon and a number.
  • For example:
#include<stdio.h>
struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};
int main()
{
	printf("%d\n", sizeof(struct A)); //8
	return 0;
}
  • A is a bit segment type. What is the size of segment a?
  • Resolution:

In the above code_ A: 2 indicates_ A requires only 2 bits_ b: 5 indicates_ b requires only 5 bits_ c: 10 indicates_ c only needs 10 bits_ d: 30 indicates_ d requires only 30 bits. Add up all these bits, a total of 47 bits. How can you get 8 bytes? You need to know the following bit segment memory allocation:

1.2. Memory allocation of bit segment

  1. The member of the bit segment can be int unsigned int signed int or char (belonging to the shaping family)
  2. The space of bit segment is opened up in the way of 4 bytes (int) or 1 byte (char) as needed.
  3. Bit segment involves many uncertain factors. Bit segment is not cross platform. Pay attention to portable programs and avoid using bit segment.
  • in summary:

_ A is an int type. First open up four bytes_ A takes up 2 bits, leaving 30 bits_ b takes up 5 bits, leaving 25 bits_ c takes up 10 bits, leaving 15 bits. The size of 15 bits is not enough_ d, and_ d is still of type int, so open up four bytes again and install it_ d, so the size of bit segment a is 8 bytes.

  • Another example:
#include<stdio.h>
struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};
int main()
{
	printf("%d\n", sizeof(struct S));//3
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	return 0;
}

At this time, a is of char type. First, open up 1 byte. A accounts for 3 bits, leaving 5 bits. b accounts for 4 bits, leaving 1 bit. It is not enough for 5 bits of c. open up 1 byte, assign 5 bits to c, leaving 3 bits. It is not enough for d. It is enough to open up 1 byte. To sum up, a size of 3 bytes is opened at this time. This situation is a waste of space. That bit was wasted, but there was no way.

  • Bit segment can save space to some extent, but it will also waste space appropriately (very small).
  • Draw pictures to explain the specific space development:

To prove the conclusion in the figure, turn on monitoring in VS compiler and look at the memory:

1.3 cross platform problem of location section

  • The bit segment itself does not support cross platform for the following reasons:
  1. It is uncertain whether the int bit field is treated as a signed number or an unsigned number.
  2. The number of the largest bits in the bit segment cannot be determined. (16 bit machines have a maximum of 16bit, 32-bit machines have a maximum of 32bit, which is written as 27bit. Problems will occur on 16 bit machines)
  3. Whether the members in the bit segment are allocated from left to right or from right to left in memory has not been defined.
  4. When a structure contains two bit segments, and the member of the second bit segment is too large to accommodate the remaining bits of the first bit segment, it is uncertain whether to discard the remaining bits or use them.
  • Summary:

Compared with the structure, bit segment can achieve the same effect, but it can save space, but there are cross platform problems.

1.4 application of bit segment

  • Compared with the structure, bit segment can achieve the same effect, but it can save space well, even if there are cross platform problems.

2. Enumeration

  • Enumeration, as the name suggests, is to enumerate one by one. List the possible values one by one.

  • For example, in our real life:
  1. Monday to Sunday of a week is a limited seven days, which can be listed one by one.
  2. Gender: male, female and confidential, which can also be listed one by one.
  3. The month has 12 months, which can also be listed one by one
  • You can use enumeration here.
  • Note: the size of enumeration types is always 4 bytes

2.1 definition of enumeration type

#include<stdio.h>
enum Day//week
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
int main()
{
	printf("%d %d %d %d %d %d %d\n", Mon, Tues, Wed, Thur, Fri, Sat, Sun);
	return 0;
}

enum Day defined above is an enumeration type. The content in {} is the possible value of enumeration type, which is also called enumeration constant. From the running results, it is not difficult to find that the enumeration has an initial value. By default, the first enumeration constant is 0, followed by + 1. Of course, initial values can also be assigned when defining.

  • For example:
#include<stdio.h>
enum Day//week
{
	Mon = 1,
	Tues,
	Wed,
	Thur = 3,
	Fri = 8,
	Sat,
	Sun = 0
};
int main()
{
	printf("%d %d %d %d %d %d %d\n", Mon, Tues, Wed, Thur, Fri, Sat, Sun);
	return 0;
}

2.2 advantages of enumeration

#define MALE 4
#define FEMALE 5
#define SECRET 6

typedef enum Sex
{
	MALE=4,
	FEMALE,
	SECRET
}Sex;
  • We can use #define to define constants. Why do we have to use enumeration?
  • Advantages of enumeration:
  1. Increase the readability and maintainability of the code
  2. Compared with #define defined identifiers, enumeration has type checking, which is more rigorous.
  3. Prevents naming contamination (encapsulation)
  4. Easy to debug
  5. Easy to use, you can define multiple constants at a time

2.3 use of enumeration

enum Color//colour
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};
enum Color clr = GREEN;//You can only assign values to enumeration variables with enumeration constants, so that there will be no type difference.
clr = 5; //ok??  err error, left and right types are inconsistent

3. United

3.1 definition of association type

  • Federation is also a special custom type

The variables defined by this type also contain a series of members, which are characterized by the fact that these members share the same space (so the union is also called the common body).

#include<stdio.h>
//Declaration of union type
union Un
{
	char c; //1
	int i;  //4
};
int main()
{
	//Definition of joint variables
	union Un u;
	//Calculate the size of the joint variable
	printf("%d\n", sizeof(u)); //4
	return 0;
}
  • The access of the consortium is similar to that of the structure Operator or - > point to operator.
union un x;
x.a = 10;
union un* p = &x;
p->a;

3.2 characteristics of joint

The members of the union share the same memory space. The size of such a union variable is at least the size of the largest member (because the union must be able to save the largest member at least)

#include<stdio.h>
union Un
{
	char c; //1
	int i;  //4
};
int main()
{
	union Un u;
	//Calculate the size of the joint variable
	printf("%d\n", sizeof(u)); 
	printf("%p\n", &u);
	printf("%p\n", &u.c);
	printf("%p\n", &u.i);
	return 0;
}

  • Using the spatial distribution of the consortium, we can skillfully judge the large and small ends:
#include<stdio.h>
union un
{
	int a;
	char b;
};
int main()
{
	union un x;
	x.a = 1;
	if (x.b == 1)
	{
		printf("Small end\n");
	}
	else
	{
		printf("Big end\n");
	}
	return 0;
}
  • Resolution:

Here, a set of binary sequences 0x 00 01 should be saved in the space corresponding to A. at this time, each of the four bytes has an address, and the address has high and low. When our data is divided according to the 1 bit bit corresponding to the byte, the data has high and low weight bits. There are two storage schemes. One is to place the high weight bit at the high address and the other is to place the low weight bit at the low address, As shown in the figure above, 01 is placed at the low address on the left, and the second scheme is opposite. As shown in the figure above, 01 is placed at the high address on the right, because B is always at the low address of a, and B occupies a byte. As shown in the figure above, x.b=1 is marked in red. If the storage scheme is the first one, b=1, if it is the second one, b=0, and the first storage scheme is the formal small end storage scheme, The second is the big end storage rule.

It is known from the operation of the compiler that it is a small end:

3.3 calculation of joint size

  1. The size of the union is at least the size of the largest member.
  2. When the maximum member size is not an integer multiple of the maximum alignment number, it should be aligned to an integer multiple of the maximum alignment number.
  • For example:
#include<stdio.h>
union Un1
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	printf("%d\n", sizeof(union Un1)); //8
	printf("%d\n", sizeof(union Un2)); //16
	return 0;
}
  • The size of parsing Un1 is 8:

Because the size of char type itself is 1 byte, while the compiler default alignment number is 8 bytes. The smaller value of alignment number is 1 byte, the size of int type itself is 4 bytes, and the smaller value of alignment number is 4 bytes. At this time, the maximum alignment number is 4 bytes, and char c[5] represents the size of at least 5 bytes. Because it is an integer multiple of the maximum alignment number 4, it is increased to 8 bytes.

  • Explain the size of Un2 16 bytes:

short c[7] represents that the size of the consortium is at least 14 bytes, the size of the short type itself is 2 bytes, and the compiler defaults to the alignment number of 8 bytes. The smaller value is 2 bytes, the int type itself is 4 bytes, and the compiler is 8 bytes. The smaller value of the alignment number is 4 bytes, and the maximum alignment number is 4 bytes, instead of 14, which is an integer multiple of 4, so it is increased to 16 bytes.

Keywords: C linq p2p

Added by zszucs on Wed, 26 Jan 2022 15:42:09 +0200