Custom types in C language (structs, enumerations, unions)

"Although there is congestion ahead, you are still on the optimal route" - AutoNavi Maps

Article directory

1. Structure type

1. Definition of structure type

2. Initialization of structure variables

3. Definition of structure type variables

4. Structure memory alignment

5. The structure realizes the bit segment

2. Enumeration type

3. Consortium type


  Hello everyone, I am Ji Ning.

  This article will mainly explain the content of custom types in C language. The custom types of C language include structure types, enumeration types, union types, etc.

1. Structure type

  Structural types are the most common custom types. The following are examples of the most common definitions and usage scenarios of structural types.

For example, define a structure type of student data, including ta's name, age, gender, student number, etc.

For example, define the data of a book with a structure type, including the title, price, author, etc. of the book

1. Definition of structure type

  When the structure type is defined outside the main function, the structure is a global variable; when the structure type is defined inside the main function, the structure is a local variable.

struct Stu
{
	char name[10];
	int age;
	char Sex[3];
	char Id[20];
};

2. Initialization of structure variables

  Initialization in order and initialization out of order, the code for the two cases is as follows:

	//按顺序初始化
	struct Stu s = { "纪宁",18,"男","123456789" };
	struct Stu S[2] = { {"纪宁",18,"男","123456789" },
						{"余微",18,"女","123456789" } };
	//不按顺序初始化,用  .操作符
	struct Stu d = { .name = "纪宁",.Id = "123456789",.Sex = "男",.age = 19 };

3. Definition of structure type variables

struct Stu
{
	char name[10];
	int age;
	char Sex[3];
	char Id[20];
}h, H[2], z;

int main()
{
	//按顺序初始化
	struct Stu s = { "纪宁",18,"男","123456789" };
	struct Stu S[2] = { {"纪宁",18,"男","123456789" },
						{"余微",18,"女","123456789" } };
	//不按顺序初始化,用  .操作符
	struct Stu d = { .name = "纪宁",.Id = "123456789",.Sex = "男",.age = 19 };
	return 0;
}

  In the case of uninitialization, the structure variable s is equivalent to the structure variable h, the structure array S[2] is equivalent to the structure array H[2], and the structure variable d is equivalent to the structure variable z.

4. Structure memory alignment

  The memory alignment of the structure is to calculate the memory size of the structure

Alignment rules for structures:

  1. The first member is at the address whose offset is 0 from the structure variable.

  2. Other member variables should be aligned to an address that is an integer multiple of a certain number (alignment number). Alignment = Compiler's default alignment and the smaller value of the member size . The default value in VS is 8. There is no default alignment number in Linux, and the alignment number is the size of the member itself 

  3. The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).

  4. If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment, and the overall size of the structure is the integer of all maximum alignments (including the alignment of the nested structure) times

struct S1
{
	char c1;
	int i;
	char c2;
};
//练习2
struct S2
{
	char c1;
	char c2;
	int i;
};
//练习3
struct S3
{
	double d;
	char c;
	int i;
};
//练习4-结构体嵌套问题
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	printf("%d\n", sizeof(struct S3));
	printf("%d\n", sizeof(struct S4));
	return 0;
}

Code running results

 Why does the computer perform structure memory alignment

  1. Platform reasons (reasons for porting): Not all hardware platforms can access any data at any address; some hardware platforms can only fetch certain types of data at certain addresses, otherwise a hardware exception is thrown.

  2. Performance reasons: Data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that to access unaligned memory, the processor needs to make two memory accesses; while aligned memory accesses require only one access .

In general: the memory alignment of structures is a practice of exchanging space for time .

  When designing the structure, we need to meet the alignment and save space. How to do it: Let the members that occupy a small space be gathered together as much as possible?

As shown in the following two pieces of code, different definition order leads to completely different results of occupied memory

struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
}

Then the summed up method of reducing memory is: let the members that occupy a small space be gathered together as much as possible.

  When the default alignment number is inappropriate, you can use #pragma pack() to modify the default alignment number, and the parameters in the brackets are the values ​​to be modified to the alignment number

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
    char c1;
    int i;
    char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
    char c1;
    int i;
    char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
    //输出的结果是什么?
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    return 0;
}

  Through the code running results, we can see that the memory space occupied by the structure under different alignment numbers is also different. 

5. The structure realizes the bit segment

  Bit fields are commonly used in IP packets . The declaration of a bit field is similar to the structure, but the bit field directly specifies the size of the space allocated to the member when it is declared, and the unit is binary bit

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

The meaning of the above code is to allocate 2 bits of memory to _a, and 5 bits of memory to _b... 

The number after the colon is the memory space allocated to the variable defined by int 

  1. The members of the bit field can be int unsigned int signed int or char (belonging to the integer family) type.

  2. The space of the bit field is opened up in the form of 4 bytes (int) or 1 byte (char) according to the need.

  3. Bit segments involve many uncertain factors. Bit segments are not cross-platform. Programs that focus on portability should avoid using bit segments .

  In general: the advantage of bit segment is that it can save memory space as much as possible, and truly achieve " allocate as much as needed "; however, the disadvantage of bit segment is also obviously its memory allocation problem, which is not suitable for cross-platform

2. Enumeration type

  Enumeration, as the name implies, is to enumerate one by one, and enumerate the possible values ​​one by one. For example in our real life:

There are only 7 days in a week from Monday to Sunday, which can be listed one by one

Gender: male, female, confidential, and can also be listed one by one.

There are 12 months in the month, and you can also list them one by one

The enumeration type is written as: keyword enum + custom name , as defined below

#include<stdio.h>​
enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
enum Sex//性别
{
	MALE,
	FEMALE,
	SECRET
};
enum Color//颜色
{
	RED,
	GREEN,
	BLUE
};

  The enum Day , enum Sex , and enum Color defined above are all enumeration types. The content in {} is the possible value of the enumeration type, also called enumeration constant. These possible values ​​are all valid, starting from 0 by default and increasing by 1 in turn. Of course, initial values ​​can also be assigned when declaring the enumeration type, for example:

enum Color//颜色
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};

  Only enumeration constants can be used to assign values ​​to enumeration variables, so that there will be no type differences, for example: 

enum Color//颜色
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};
enum Color clr = GREEN;

Advantages of Enums

1. Increase the readability and maintainability of the code
2. Compared with the identifier defined by #define, the enumeration has type checking, which is more rigorous.
3. Easy to debug (constants defined by #define cannot be debugged)
4. Easy to use, multiple constants can be defined at a time

3. Consortium type

  A union is a special custom type whose method of defining variables and members is similar to that of a structure. Variables defined by this type also contain a series of members, characterized by the fact that these members share the same space (so unions are also called unions). Because all its members share a memory space, the size of the union variable is at least the largest one among the union members

  The writing method of the union type is: keyword union + custom name , as follows

union Un
{
	int i;
	char c;
};
int main()
{
	union Un un;
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
	return 0;
}

  It can be seen from the running results that the address of the member i of the int type and the member c of the char type are the same, which verifies the rule that they share a space.

  The size calculation rule of the union type: the size of the union type is at least the size of the largest member; the size of the union type must be an integer multiple of the maximum alignment (this is the same as the structure)

insert image description here

  The blogger has been writing for a long time, if you can give the blogger a free triple combo to encourage the blogger, then I think your Thai pants are really spicy! ! !

Guess you like

Origin blog.csdn.net/zyb___/article/details/131730987