Custom type: structure, enumeration, union

catalogue

1, Structure

1.1 declaration of structure

1.2 special declaration: anonymous struct type

1.3 structure self reference

1.4 definition and initialization of structure variables

1.5 structure memory alignment

1.5.1 why is there memory alignment?

1.6 modify the default alignment number

 1.7 offsetof:

1.8 structural transmission parameters

2.1 what is a bit segment

2.2 memory allocation of bit segment

2.3 cross platform problem of bit segment

2, Enumeration

1.1 advantages of enumeration

1.2 use of enumeration constants

3, Consortium (Consortium)

1.1 characteristics of the Consortium

1.2} face to face questions

1.3 calculation of consortium size

1, Structure

1.1 declaration of structure

//Declare a struct type
//A structure is a collection of values called member variables. Each member of the structure can be a different type of variable.
struct Book
{
	char name[20];
	char author[20];
	int price;
}b1,b2;//overall situation
struct Book b3;//overall situation
int main()
{
	struct Book b4;//local variable

	return 0;
}

1.2 special declaration: anonymous struct type

//Anonymous structure -- can only be used once
struct   //Structure labels are omitted
{
	char a;
	int b;
	double c;
}x;//Global variable, which will be destroyed at the end of the program

On the basis of the above code, declare a structure pointer p with the same members, then

p = &x; Is it legal?

struct
{
	char a;
	int b;
	double c;
}x;//Global variable, which will be destroyed at the end of the program
struct
{
	char a;
	int b;
	double c;
}*p;

int main()
{
	p = &x;//The types from '*' to '*' are incompatible. They are two different types
}
be careful:
The compiler will treat the above two declarations as two completely different types.
So it's illegal.

1.3 structure self reference

//Self reference of structure: include a member whose type is the structure itself in the structure
struct Node
{
	int data;
	struct Node* Next;
};

typedef struct Node//The structure label node cannot be omitted
{
	int data;
	struct Node* Next;
} Node;

1.4 definition and initialization of structure variables

struct Point
{
	int x;
	int y;
}p3 = { 5,6 }, p4 = { 7,8 }; //Define variables P3 and P4 while declaring types

struct Point p2 = { 1,2 };//Initialization: define variables and assign initial values at the same time

struct S
{
	double d;
	struct Point p;//The structure contains the structure
	char name[20];
	char data[20];
};
int main()
{
	struct Point p1 = { 3,4 };
	struct S s = { 3.14,{3,4},"zhangsan",{1,2,3} };//Structure nesting initialization
	printf("%lf\n", s.d);
	printf("%d %d\n", s.p.x, s.p.y);
	printf("%s\n", s.name);
	int i = 0;
	for (i = 0;i < 20;i++)
	{
		printf("%d ",s.data[i]);
	}
	return 0;
}

1.5 structure memory alignment

Illustration:

 

 

 

1.5.1 why is there memory alignment?

1. Platform reason (migration reason)

Not all hardware platforms can access any data at any address; Some hardware platforms can only get certain types of data at certain 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 the misaligned memory, the processor needs to make two memory accesses; Second aligned memory access requires only one access.

in general:

Memory alignment of structures is a method of trading space for time.

When designing the structure, we should not only meet the alignment, but also save space: let the members with small space gather together as much as possible

Summary: the members of S1 and S2 are the same, but the space occupied by S1 and S2 is different

1.6 modify the default alignment number

When the alignment is not appropriate, we can change the default alignment number, which is generally modified to the power of 2

 1.7 offsetof:

Implementation of macro -- > calculate the offset of a variable in the structure relative to the first address

1.8 structural transmission parameters

struct S
{
	int data[1000];
	int num;
};
void print(struct S tmp)
{
	int i = 0;
	for (i = 0;i < 6;i++)
	{
		printf("%d ",tmp.data[i]);
	}
	printf("\nnum = %d\n",tmp.num);
}
void print1(const struct S* s1)
{
	int i = 0;
	for (i = 0; i < 6; i++)
	{
		printf("%d ",(s1->data)[i]);
	}
	printf("\nnum = %d\n", s1->num);
}
int main()
{
	struct S s = { {1,2,3,4,5,6},100 };
	print(s);//pass by value
	print1(&s);//Address delivery
	return 0;
}

Which of the above print and print1 functions is better?
print1 is preferred because the parameters need to be stacked when the function passes parameters, which will have system overhead in time and space.

If the structure is too large when passing a structure object, the system overhead of parameter stack pressing is relatively large, which will lead to performance degradation.

Conclusion: when the structure passes parameters, the address of the structure should be passed.

2.1 what is a bit segment

The declaration and structure of bit segments are similar, with two differences:

1. The member of the bit segment must be int, unsigned int or signed int.

2. The member name of the bit field is followed by a colon and a number.

2.2 memory allocation of bit segment

1. The members of the bit segment can be int unsigned int signed int Or char (belonging to plastic family)
2. The space of bit segments is as needed 4 Bytes( int )Or 1 Bytes( char )The way to open up.
3. Bit segment involves many uncertain factors. Bit segment is not cross platform. Pay attention to portable programs and avoid using bit segment.
Explanation: open up one byte at a time. When the next byte is not enough, open up another byte. The previous space is wasted

2.3 cross platform problem of bit segment

1. int It is uncertain whether a bit segment 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 machine Max 16 , 32 Bit machine Max 32 , written as 27 , in 16 Bit machine
There will be problems with the filter.
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, yes
It is uncertain whether to discard the remaining bits or use them
Conclusion: compared with the structure, bit segment can achieve the same effect, but it can save space, but cross platform problems also exist.
Enumeration constants:
//enumeration constant 
enum Color //Enumeration type
{
	Red,//Enumeration constant, whose size is fixed, is an integer variable with size bit 4B
	Green = 3,
	Blue
};

int main()
{
	//These enumeration constants start from 0 by default and increase by 1 at a time. They can also be given initial values when defined
	printf("%d\n",Red);//0
	printf("%d\n", Green);//3
	printf("%d\n", Blue);//4
	return 0;
}
//Usage:
enum Color 
{
	Red = 2,
	Green = 3,
	Blue = 5
};

int main()
{
	enum Color c = Green; //You can only assign values to enumeration variables with enumeration constants, so that there will be no type difference.
	
	if (c == Green)
	{
		printf("green\n");//green
	}
	return 0;
}

2, Enumeration

1.1 advantages of enumeration

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. Prevent naming pollution (packaging)

4. Enumeration can be debugged, but #define cannot be seen during debugging

5. It is easy to use, and multiple constants can be defined at one time

1.2 use of enumeration constants

//Use of enumerated constants:
void menu()
{
	printf("*****************************\n");
	printf("****1.add  2.sub*************\n");
	printf("****3.mul  4. div************\n");
	printf("****0. exit    **************\n");
}
enum
{
	exit,//0
	add,//1
	sub,//2
	mul,//3
	div//4
};
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("Please select:>");
		
		scanf("%d", &input);
		switch (input)
		{
			case add: break;
			case sub: break;
			case mul: break;
			case div: break;
			case exit: break;
		}
	} while(input);
}

3, Consortium (Consortium)

1.1 characteristics of the Consortium

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 of the Union)
At least have the ability to save the largest member).
union Un
{
	char c;
	int i;
};
int main()
{
	union Un u = {0};
	printf("%d\n",sizeof(u));// 4
	printf("%p\n",&u); //012FFE8C
	printf("%p\n", &(u.c));// 012FFE8C
	printf("%p\n", &(u.i)); //012FFE8C
	return 0;
}

1.2} face to face questions

Determine the storage size of the current computer?

int main()
{
	int a = 1;

	//Writing method 1:
	//0x 00 00 00 01
	//01 00 00 small end storage
	//00 01 big end storage
	char* pc = (char*)&a;
	if (*pc == 1)
	{
		printf("Small end\n");//Small end
	}
	else
	{
		printf("Big end\n");
	}

	//Writing method 2: in the form of consortium, the same space is shared, but the two variables cannot be used at the same time
	union U
	{
		char c;
		int i;
	}u;
	u.i = 1;
	if (u.c == 1)
	{
		printf("Small end\n");//Small end
	}
	else
	{
		printf("Big end\n");
	}
	return 0;
}

1.3 calculation of consortium size

1. The size of the consortium shall be at least the size of the largest member

2. When the 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

int main()
{
	union Un1
	{
		char c[5];
		int i;
	};
	union Un2
	{
		short c[7];
		int i;
	};
	
	printf("%d\n", sizeof(union Un1)); //8
	printf("%d\n", sizeof(union Un2)); //16
}

 

This article is the sorting of knowledge points of user-defined types: structure, enumeration and Consortium (common body). If there are errors, please comment more in the comment area. Ha, come on! 😄

Keywords: C C++

Added by jikishlove on Tue, 01 Mar 2022 16:20:59 +0200