[C Advanced] Custom Type (1) Structure

content

1. Basic knowledge of structures

2, the declaration of the structure

3. Special statement

4. Self-reference of structures

5. Definition and initialization of structure variables

6. Structure memory alignment

     Exercise 1

     Exercise 2

     Exercise 3

     Exercise 4 - Structure Nesting Problem

7. Modify the default alignment number

8. Structure parameters


1. Basic knowledge of structures

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

2, the declaration of the structure

  • Basic syntax:
//struct:结构体的关键字
struct tag  //tag:结构体标签
{
    //大括号内容:结构体相关属性
	member - list; //member - list:成员列表
}variable - list; //变量列表
  • For example to describe a student:
#include<stdio.h>
//结构体类型
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}s2, s3, s4; //分号不能丢
//变量列表可有可无,不过上述的s2,s3,s4都是全局变量
int main()
{
	struct Stu s1; //结构体变量
	return 0;
}

3. Special statement

  • When declaring a structure, you can declare it incompletely.
  • for example:
//匿名结构体类型
struct  //去掉标签
{
	int a;
	char b;
	float c;
}x;
struct
{
	int a;
	char b;
	float c;
}a[20], * p;

The above two structures are declared without the structure tag (tag). is an anonymous struct type

When defining a variable of an anonymous structure variable type, it must be defined after the structure { }, otherwise it will not work. as above

  • So here comes the question?
//在上面代码的基础上,下面的代码合法吗?
p = &x;
  • warn:

The compiler thinks that the two sides of the equal sign are of different structure types, so this way of writing is wrong.

4. Self-reference of structures

  • Is it OK to have a member of type the struct itself in a struct?
//代码1
struct Node
{
	int data;
	struct Node next;
};
//可行否? err
  • If so, what is sizeof(struct Node)?

This structure contains an integer type of 4 bytes, and then contains a structure variable... and so on, infinite nesting dolls, and the infinite loop continues without knowing what the size is.

  • Correct self-reference method: To store the address of the next node, just give the previous pointer.
//代码2
struct Node
{
	int data;
	struct Node* next;
};
  • Notice:
//代码3
typedef struct
{
	int data;
	Node* next;
}Node;
//这样写代码,可行否? err
  • solution:
typedef struct Node
{
	int data;
	struct Node* next;
}Node;

5. Definition and initialization of structure variables

struct Point
{
	int x;
	int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = { x, y };

struct Stu //类型声明
{
	char name[15];//名字
	int age; //年龄
};
struct Stu s = { "zhangsan", 20 };//初始化

struct Node
{
	int data;
	struct Point p;
	struct Node* next;
}n1 = { 10, {4,5}, NULL }; //结构体嵌套初始化
struct Node n2 = { 20, {5, 6}, NULL };//结构体嵌套初始化

6. Structure memory alignment

  • Alignment rule:
  1.  The first member is at the address at offset 0 from the structure variable.
  2.  Other member variables should be aligned to an address that is an integer multiple of a number (alignment number). Alignment = the smaller of the compiler's default alignment and the size of the member. The default value in VS is 8
  3.  The total size of the structure is an integer multiple of the maximum alignment (each member variable has an alignment).
  4.  If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number, and the overall size of the structure is an integer multiple of all maximum alignment numbers (including the alignment number of nested structures).

Before doing the question, you must first know one thing - offsetof - offset (calculate the offset of a structure member compared to the starting position of the structure)

     Exercise 1

#include <stdio.h>
#include <stddef.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
// 结构体 S1 的大小是多大?  ---》12
int main()
{
	printf("%d\n", sizeof(struct S1));    //12
	//计算偏移量
	printf("%d\n", offsetof(struct S1, c1));  //0
	printf("%d\n", offsetof(struct S1, i));   //4
	printf("%d\n", offsetof(struct S1, c2));  //8
	return 0;
}

     Exercise 2

struct S2
{
	char c1;
	char c2;
	int i;
};
// 结构体 S2 的大小是多大?  ---》8

     Exercise 3

struct S3
{
	double d;
	char c;
	int i;
};
// 结构体 S3 的大小是多大?  ---》16

     Exercise 4 - Structure Nesting Problem

 struct S4
 {
	 char c1;
	 struct S3 s3;
	 double d;
 };
 // 结构体 S4 的大小是多大?  ---》32

Why does memory alignment exist?

  • 1. Platform reasons (migration reasons):

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 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 unaligned memory, the processor needs to make two memory accesses; aligned memory accesses require only one access.

  • Drawing comprehension:
  • Not aligned:

The cpu reads 4 bytes at a time in a 32-bit environment. The last 3 bytes of the first read and the first 1 byte of the second read are the data of my i.

  •  Align:

 If it is aligned, the data of i can be obtained by reading it once. Alignment is more efficient.

  • In general:

The memory alignment of structures is the practice of trading space for time.

  • When designing a structure, we must not only satisfy the alignment, but also save space. How to do it?

Keep members with a small footprint as close together as possible.

  • E.g:
struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};

The members of the S1 and S2 types are exactly the same, but there are some differences in the size of the space occupied by S1 and S2. The size of S1 is 12 bytes, and the size of S2 is 8 bytes. The creation method of S2 not only satisfies the alignment, but also saves space, which is better.

7. Modify the default alignment number

  • VS default alignment number is 8, but we can modify it.
#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));  //12
	printf("%d\n", sizeof(struct S2));  //6
	return 0;
}
  • in conclusion:

When the alignment of the structure is not suitable, we can change the default alignment by ourselves.

8. Structure parameters

  • Look at the code:
#include<stdio.h>
struct S
{
	int data[1000];
	int num;
};
struct S s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{
	printf("%d\n", s.num);   //1000
}
//结构体地址传参
void print2(struct S* ps)
{
	printf("%d\n", ps->num); //1000
}
int main()
{
	print1(s); //传结构体
	print2(&s); //传地址
	return 0;
}
  • Which of the above print1 and print2 functions is better?
  • The answer is: the print2 function is preferred.
  • reason:
  1. When passing parameters to a function, the parameters need to be pushed onto the stack, which will result in system overhead in terms of time and space.
  2. If a structure object is passed, the structure is too large, and the system overhead of parameter stacking is relatively large, so the performance will be degraded.
  • Conclusion: When the structure is passed parameters, the address of the structure must be passed.

Guess you like

Origin blog.csdn.net/bit_zyx/article/details/122657181