Custom type

C language built-in type char short int long float double

Custom type struct enumeration Union

1. Structure

1.1 declaration of structure type

A structure is a collection of values called member variables. Each member of the structure can be a different type of variable.

//Declare a struct type
struct Book
{
	char name[20];
	char author[20];
	int price;

};

struct Book
{
	char name[20];
	char author[20];
	int price;

}b1, b2;//global variable

struct Book b3;//global variable

int main()
{
	struct Book b4;//local variable

	return 0;
}
//Declaring anonymous struct types
struct
{
	int a;
	char c;
	double d;
}s1, s2;//You must create it directly here

struct
{
	int a;
	char c;
	double d;
}*ps;

int main()
{
	struct s3;//err

	ps = &s1;//err, incompatible type, illegal operation

	return 0;
}

1.2 self reference of structure

//Data storage in memory: linear data construction: sequential table chain table: node

//err
struct Node
{
	int data;
	struct Node n;
};

//Structure of node
struct Node
{
	int data;//Data domain
	struct Node* next;//Pointer field
    //Self reference of structure
};

typedef struct Node
{
	int data;//Data domain
	struct Node* next;//Pointer field
    //Self reference of structure
}Node;

1.3 definition and initialization of structure variables

struct Point
{
	int x;
	int y;
}p3 = { 5,6 },p4 = { 7,8 };

struct Point p2 = { 1,2 };

struct S
{
	double d;
	struct Point p;
	char name[20];
	int data[20];
};

int main()
{
	struct Point p1 = { 3,4 };
	
	struct S s = { 3.14,{1,5},"zhangsan",{1,2,3} };
	
	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.4 structure memory alignment

//Rules for structure memory alignment:
//1. The first member of the structure is always placed at the position where the offset of the starting position of the structure is 0
//2. Starting from the second structure member, it is always placed at an integer multiple of an alignment number.
//3. Alignment number = the compiler's default alignment number and the smaller value of the variable's own size. linux - no default alignment number, vs - the default alignment number is 8
//4. The total size of the structure must be an integer multiple of the maximum number of alignments of each member.
//5. If a structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number, and the overall size of the structure is an integer multiple of all the maximum alignment numbers (including the alignment number of nested structures).

//12
struct S1
{
	char c1;
	int a;
	char c2;
};
//8
struct S2
{
	char c1;
	char c2;
	int a;
};
//16
struct S3
{
	double d;
	char c;
	int i;
};
//32
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};

int main()
{
	struct S1 s = { 'x',100,'y' };
	
	printf("%d\n", sizeof(struct S1));//12
	printf("%d\n", sizeof(struct S2));//8
	printf("%d\n", sizeof(struct S3));//16
	printf("%d\n", sizeof(struct S4));//32

	return 0;
}

//Structure alignment reason
//1. Platform 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 reason: 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 make two memory accesses; Aligned memory access requires only one access

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. How to do this:

Let the members with small space gather together as much as possible

struct S2
{
	char c1;
	char c2;
	int a;
};

struct S1
{
	char c1;
	int a;
	char c2;
};

int main()
{
	struct S1 s1 = { 0 };
	printf("%d\n", sizeof(s1));//12
    printf("%d\n", sizeof(s2));//8
	return 0;
}

Modify the default number of alignments

#pragma pack(1)
struct S1
{
	char c1;
	int a;
	char c2;
};
#pragma pack()
int main()
{
	struct S1 s1 = { 0 };
	printf("%d\n", sizeof(s1));
    
    //offsetof is a macro that calculates the offset of a variable in the structure relative to the first address
	printf("%u\n", offsetof(struct S1, c1));
	printf("%u\n", offsetof(struct S1, a));
	printf("%u\n", offsetof(struct S1, c2));
	return 0;
}

1.5 structural transmission parameters

struct S 
{
	int data[1000];
	int num;
};

void print1(struct S tmp)
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", tmp.data[i]);
	}

	printf("\n%d\n", tmp.num);
}

void print2(const struct S* ps)
{
	//->
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->data[i]);
	}

	printf("\n%d\n", ps->num);
}

int main()
{
	struct S s = { {1,2,3,4,5,6,7,8,9,10},100 };

	print1(s);//Value transmission, to open up a new space 
	print2(&s);//Address, no more space

	return 0;
}

When a function passes parameters, the parameters need to be pressed on the stack, 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 a structure passes parameters, the address of the structure should be passed.

1.6 structure realization bit segment (filling & portability of bit segment)

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

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

2. There is a colon and a number after the member name of the bit field.

//Bit segments can save space!
//Bit segment - binary bit
struct A
{
	int _a : 2;  //_ a 2 bit
	int _b : 5;  //_ b 5 bit
	int _c : 10; //_ c 10 bit
	int _d : 30; //_ d 30 bit
};
//47bit (theoretical 6byte) actual 8byte
Memory allocation for bit segments
1. The members of the bit segment can be int unsigned int signed int Or char (Belongs to plastic family)
2. The space of the bit segment is 4 bytes as required( int )Or 1 byte( char )The way to open up.
3. Bit segments involve many uncertain factors. Bit segments are not cross platform. Pay attention to portable programs and avoid using bit segments.
struct S {
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

int main()
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;

	return 0;
}

Cross platform problem of bit segment

\1. It is uncertain whether the int bit field is regarded as a signed number or an unsigned number.

\2. The maximum number of bits in the bit field cannot be determined. (16 bit machines are 16 at most, 32-bit machines are 32 at most, which is written as 27. There will be problems 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, the remaining bits are discarded

Or use, it's uncertain.

summary

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

application

2. Enumeration

2.1 definition of enumeration type

enum Day//week
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

enum Sex//Gender
{
	MALE,
	FEMALE,
	SECRET,
};

enum Color//colour
{
	RED = 2,
	GREEN = 4,
	BLUE = 8,
};

These possible values have values. By default, they start from 0 and increase by 1 at a time. Of course, initial values can also be assigned when defining.

2.2 advantages of enumeration

#define RED  2
#define GREEN  4
#define BLUE  8

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. Convenient for debugging

\5. Easy to use, multiple constants can be defined 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; //err
enum Option
{
	EXIT,//0
	ADD,//1
	SUB,//2
	MUL,//3
	DIV//4
};

void menu()
{
	printf("******************************\n");
	printf("**** 1. add     2. sub    ****\n");
	printf("**** 3. mul     4. div    ****\n");
	printf("**** 0. exit              ****\n");
	printf("******************************\n");
}

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 ();
	return 0;
}

3. United Nations

3.1 definition of association type

Union is also a special user-defined type. The variables defined by this type also contain a series of members. The characteristic is that these members share the same space (so union is also called common body).

union Un
{
	char c;//1
	int i;//4
};

int main()
{
	union Un u = { 0 };
	//printf("%d\n", sizeof(u));//4
	
	printf("%p\n", &u);
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	
	return 0;
}

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 have at least

The member with the greatest ability to save).

3.3 calculation of joint size

The size of the union is at least the size of the largest member.

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.

union Un1
{
	char c[5];//5	1
	int i;	  //4   4
};
union Un2
{
	short c[7];//14	2
	int i;//4	4
};

int main()
{
	printf("%d\n", sizeof(union Un1));//8
	printf("%d\n", sizeof(union Un2));//16

	return 0;
}
//Determine the storage size of the current computer
int main()
{
	int a = 1;//0x 00 00 00 01
	//Low < ---------------- > High
	//01 00 00 small end storage
	//00 01 big end storage
	char* pc = (char*)&a;
	if (*pc == 1)
	{
		printf("Small end storage\n");
	}
	else
	{
		printf("Big end storage\n");
	}
	
	return 0;
}
int main()
{
	union U
	{
		char c;
		int i;
	}u;
	
	u.i = 1;
	
	if (u.c == 1)
	{
		printf("Small end storage\n");
	}
	else
	{
		printf("Big end storage\n");
	}

	return 0;
}
int check_sys()
{
	union U
	{
		char c;
		int i;
	}u;
	
	u.i = 1;

	return u.c;
}

int main()
{
	if (check_sys() == 1)
	{
		printf("Small end storage\n");
	}
	else
	{
		printf("Big end storage\n");
	}

	return 0;
}

Keywords: C

Added by Retired Bill on Fri, 15 Oct 2021 23:52:21 +0300