Detailed explanation of the use of structure, bit segment, enumeration and union

Structure

When it comes to structures, we will pay attention to the declaration of the structure, the self-referencing of the structure and the size of the structure. Next, we mainly analyze how the size of the structure is calculated, and the size of the structure is closely related to the memory alignment in the structure. We analyze the memory alignment in the structure to get the size of the structure.

Memory alignment in the structure

The principle of memory alignment in the structure:

  • The first member is at an address with an offset of 0 from the structure variable .
  • Starting from the second member, it is necessary to align to an address that is an integral multiple of the " alignment number "
  • For the nested structure of the structure, the nested structure to be aligned to their maximum alignment at integer multiples
  • The total size of the structure is the maximum alignment integral multiple (number of alignment contains nested structure)

Alignments: alignment number = compiler default number is aligned with the size of the members of a small value ( VS aligned default number 8, Linux no alignment default number )

Offset calculation

We can use the offset macro to calculate the offset of the structure members.

size_t offsetof( structure name ,  member variable  );

Simulation implementation of offsetof macro:

We can use 0 as the address , force it to the structure type, and then visit its member variable, because the offset = the address of the member variable-the address of the starting position of the structure is its offset , at this time Since the structure of the starting address is 0 , and therefore to the address variable is the members of the offset member variable , then finally (int) to turn strong.

#define OFFSETOF(struct_name,member_name) (int)&(((struct_name*)0)->member_name)

struct S
{
	char a;
	int b;
	short c;
};

int main()
{
	int ret = OFFSETOF(struct S, b);
	printf("%d\n", ret);
	return 0;
}

Modify the default alignment

We can use the #pragma preprocessing directive to change the default alignment. (Generally we will change the default alignment number to 2^n)

//此时下面的结构体就是以编译器的默认对齐数为4来进行内存对齐的
#pragma pack(4)
struct S
{
	char a;
	int b;
	char c;
};
//设置过后要进行取消
#pragma pack()

Structure parameter transfer

When passing a structure parameter, pass the address of the structure.

the reason:

  • When a function is passed parameters, the parameters need to be pushed onto the stack, which will cause system overhead in time and space.
  • If the structure is too large when passing a structure object, the system overhead of parameter stacking will be relatively large, which will cause performance degradation.

 

Bit segment

Position and structure are similar, but there are two differences

  1. The members of the bit segment must be an integer family: int (unsigned int, signed int), char, short [float, double cannot exist]
  2. After the member name of the position, add : and number

Shaped like:

struct A
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;
};

Memory allocation in bit segment

When the bit segment is opened up, it is opened up in the form of 1 byte (char) or 4 bytes (int).

However, due to the cross-platform problem of the position, there are many uncertainties.

Cross-platform issues

  • It is uncertain whether the int bit field is treated as a signed number or an unsigned number
  • The maximum number of bits in the bit segment cannot be determined (16-bit machines are up to 16, 32-bit machines are up to 32, and 20 on 32-bit machines will cause problems on 16-bit machines)
  • Whether the members of the bit segment are allocated from left to right in memory or from right to left is undefined
  • When a structure has two bit segments, and the second bit segment member is relatively large and cannot fit in the remaining bits of the first bit segment, it is impossible to determine whether to discard the remaining bits or use them.

 

enumerate

Use of enum

Advantages of enumeration

  • Easy to use, multiple variables can be defined at once
  • Easy to debug
  • Prevent naming pollution
  • Increased the readability and maintainability of the code
  • Compared with the identifier defined by #define, enumeration has type checking, which is more rigorous

 

joint

The members of the union share the same memory space, so for the size of a union variable, it is at least the size of the largest member.

union UN
{
	int i;
	char c;
};

Note: The joint members i and c cannot be used at the same time .

Calculation of joint size

  • The size of the union is at least the size of the largest member
  • When the size of the largest member is not an integral multiple of the maximum alignment , it should be aligned to an integral multiple of the maximum alignment

 

Use union to judge large and small storage

Save the integer 1 through the int in the union, and then access it through the char of the union, so that if it is stored in little endian , it will be accessed to 01 , if it is big endian it is 00

union UN
{
	int i;
	char c;
};

int check_sys()
{
	union UN u;
	u.i = 1;
	return u.c;
}

int main()
{
	if (check_sys())
	{
		printf("小端");
	}
	else
	{
		printf("大端");
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_51696091/article/details/114518515