Relevant bit segment, structure, Consortium

Posted by tjodolv on Sun, 23 Jan 2022 19:47:46 +0100

#Foreword

There are two similar structures in C language, which are structure and union. Today, let's take a look at the relevant contents of these two structures.

#Structure

1. Declaration of structure

The declaration of structure is made with struct keyword. The specific code is as follows:

typedef struct Stu{
	char name[20];
	int age;
	int grade;
	char Id_card[20];
}Stu;

typedef is the renamed keyword, which renames the structure type struct Stu to Stu, which is convenient for our subsequent use. However, the following statement is wrong, and the code is as follows:

typedef struct Stu{
	char name[20];
	int age;
	int grade;
	char Id_card[20];
	Stu* stu;//Since struct Stu has not been renamed Stu, it cannot be used in advance
}Stu;//This is where the Rename is complete

The correct writing method should be to continue to use struct Stu* stu.

2. Initialization of structure

Structure has two initialization methods. Let's take the student structure above as an example to illustrate its declaration method.

First:

typedef struct Stu{
	char name[20];
	int age;
	int grade;
	char Id_card[20];
}Stu;


Stu stu = { "zhangsan", 20,558,"350000000000"};

At this point, we can directly initialize in braces according to its corresponding type.

Second:

typedef struct Stu{
	char name[20];
	int age;
	int grade;
	char Id_card[20];
}Stu;

Stu stu;
	stu.name[20] = "zhangsan";
	stu.age = 20;
	stu.grade = 550;
	stu.Id_card[20] = "35000000000";

In this case, we will use "." respectively for the corresponding members Operator.

3. Calculation of structure size

The memory size calculation of a structure is different from that of an array. It is not the sum of the type sizes of all elements in the type. This is because the structure will perform a memory alignment, which makes its memory size not so easy to calculate. We will talk about the benefits of memory alignment later.

Now let's talk about the rules of memory alignment. The specific rules are as follows:

Similarly, let's take the above student type as an example to calculate its size. Before we start, we still need to understand a concept, that is, alignment number. Alignment number includes the size of the type itself (if it is an array, it is the size of its array type) and the default alignment number of the compiler. In vs2019, the default alignment number is 8, which will be used as the standard for our subsequent calculations.

typedef struct Stu{
	char name[20];//0-19, its own type is char, the alignment number is 1, and the default alignment number is 8, so the alignment number is 1. The same is true below
	int age;//20-23, alignment number is 4
	int grade;//24-27, alignment number is 4
	char Id_card[20];//28-47, alignment number is 1
    //At this time, the total byte size at the calculation is 48, and the total byte should be an integer multiple of the maximum alignment number, so it can be 48
}Stu;

Next, let's take another example:

struct A {
	char a;//The number of alignments is 1, starting at an offset of 0
	int b;//The alignment number is 4. Since 1 is not a multiple of 4, it is offset from 4, 4-7
	double c;//The alignment number is 8, and the next 8 is exactly a multiple of the 8 alignment number 8, so it is offset from 8, 8-15
    //At this time, the total byte size is 16, which is exactly a multiple of the maximum alignment number 8, so it is 16
};

Next, let's look at a special case, that is, a structure is nested in a structure, and what is its size?

struct A {
	char a;
	int b;
	double c;
};

typedef struct Stu{
	char name[20];//The number of alignments is 1, 0-19
	int age;//The number of alignments is 4, 20-23
	int grade;//The number of alignments is 4, 24-27
	char Id_card[20];//The number of alignments is 1, 28-47
	struct A a;//Its size is 16, the number of alignments is, and the maximum number of alignments of internal elements is 8, 48-63
    //The total size is 64 at this time, which is a multiple of the maximum alignment number 8, so it is 64.
}Stu;

4. Alignment number

Although the compiler has its own default alignment number, we can modify it ourselves. The code is as follows:

#pragma pack(4)
struct A {
	char a;
	int b;
	double c;
};
typedef struct Stu{
	char name[20];
	int age;
	int grade;
	char Id_card[20];
	struct A e;
}Stu;
#pragma pack()

The alignment number is changed from 8 to 4. Finally, why do we have aligned numbers? The specific reasons are as follows:

1. Platform reasons

Not all hardware platforms can access any data at any address; Some hardware platforms can only get some specific data types at some addresses, otherwise hardware exceptions will be thrown.

2. Performance reasons

Data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that in order to access misaligned memory, the processor needs to perform two memory access operations, while aligned memory access only needs one operation, which is essentially a practice of exchanging space for time.

#Consortium

 1. Statement of consortium

The declaration of the consortium is similar to that of the structure. We won't talk about it here. We just change the struct keyword to the union keyword. The specific code is as follows:

typedef union S {
    int a;
    char c;	
}S;

The initialization of the consortium is different from that of the structure. There is only the constant initialization method. The specific code is as follows:

    S s;
	s.a = 100;
	s.c = 'a';

2. Size of consortium

Let's look at the following code:

#include<stdio.h>

typedef union S {
	char c;
	int a;
}S;

int main() {
	S s;
	s.a = 100;
	s.c = 'a';
	printf("%c\n", s.c);
	printf("%d", s.a);
	return 0;
}

What will this code print out? Most people may think that it is to print out 100 and character a, but in fact, the printed results are as follows:

So why? This is related to the size of the consortium we talked about next. In fact, the consortium is called a consortium because its internal variables share a space. Of course, the space occupied is at least the size of its internal maximum type, and it needs to be adjusted according to the maximum alignment number (which should be an integer multiple of the maximum alignment number). Here, its size is 4 bytes. Therefore, after assigning s.a to 100, we assign character a to s.c. and the ASCII code of character a is 97, so it will be covered by 100. The details can be viewed during debugging, as follows:

 

#Bit segment

1. Function of bit segment

The function of bit segment is to reduce memory consumption by determining the byte size required to define the type.

2. Statement of bit segment

struct s {
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

Specifically, as stated above, the number followed is in bits, indicating the memory space required for its corresponding variable.

3. Size of structure after bit segment declaration

As shown in the figure above, a variable is created at the beginning. Its size is 1 byte = = 8bit, so it can be used by variables A and b, 4 + 3 < 8. Then the remaining byte is not enough for the next variable C, so we discard this byte and recreate the space (in fact, whether to discard the extra byte is not clearly specified in C language, because this byte space is not used in vs2019, which depends on the compiler). So next, a space of 1 byte is created. C uses 5 bytes, and the remaining 3 bytes are not enough for variable d, so don't give up. We are re creating a space of 1 byte to store variable d. So its total size is 3 bytes.

Topics: C