结构体的总结

本文详细介绍了C语言中结构体的定义、重命名、与指针及数组的结合使用、结构体大小计算、嵌套使用、动态内存分配及学生成绩排序等应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

一、结构体的定义

二、对结构体的重命名

三、结构体和指针的结合

四、结构体和数组的结合

五、结构体大小

六、结构体嵌套

七、动态内存与结构体

八、总结(用结构体对学生成绩实行升序排序)

一、结构体的定义 

我们之前接触的数据类型有:基本数据类型(内置类型),而结构体类型是用户自定义的数据类型

1.设计一个类型
struct 类型名{
   属性(变量的声明)       
};
设计一个学生类型
struct Student{
char name[10];   <=>   const char *name
int age;
int score;
}; 

注意:在纯c代码中,类型前面必须加struct,如:struct Student stu={“zs”,10,100};
//通过结构体变量来进行成员的访问:stu.name。那如果想要在纯c和c++都能用,我们就要进行结构体的重命名了

二、结构体的重命名 

第一种方式:

typedef struct Student {
char name[10];
int age;
int score;
}Student,*stu;//表示类型重命名后新的名字
int main(){
Student s={"zs".10,100};//将结构体(struct)省略掉了,在纯c代码和c++中都能适用
}

第二种方式:

struct Student{
char name[10];——>const char *name
int age;
int score;
}; 
typedef struct Student Student;
typedef struct Student  *stu;

三、结构体和指针的结合 

int main(){
Student *ptr=&s;   <=>   stu ptr=&s;
(*ptr).uname;   //因为点(.)的优先级高于(*),所以我们的指针要加括号
ptr->name ;   //指向符具有解引用的功能,所以和上面的式子相同
}

代码如下:

typedef struct Student {
	const char* name;
	int age;
	int score;
}stu;
int main() {
	stu s = { "zs",10,100 };
	stu* ptr = &s;
	printf("%s\n%d\n%d\n", (*ptr).name, (*ptr).age, ptr->score);
}

运行结果;

zs
10
100

D:\c程序\p2-2\Debug\p2-2.exe (进程 11476)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

四、结构体和数组的结合 

定义一个结构体类型的数组,赋值,数据打印
如:struct Student arr[]={{"zs".10,100},{"ww",8,88}};// 此时 arr+1加的是一个结构体

我们通过代码将整个流程走一下:

typedef struct Student {
	const char* name;
	int age;
	int score;
}stu;
int main() {
	stu arr[] = { {"zs",10,100},{"ls",8,97},{"ww",9,97} };
	int len = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < len; i++) {
		printf("%s %d %d\n", arr[i].name, arr[i].age, arr[i].score);
	}
}

运行结果:

zs 10 100
ls 8 97
ww 9 97

D:\c程序\p2-2\Debug\p2-2.exe (进程 16672)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

 五、结构体的大小

在计算结构体的大小时候,并不像我们平时计算基本数据类型大小那样,这里存在内存对齐方式,从而去计算它的大小,现在总结以下三点:

1)结构体变量的首地址,必须是 MIN(结构体变量中最大基本数据类型,指定对齐方式)的成员所占字节数的整数倍
2)结构体变量中每个成员相对结构体变量的首地址的偏移量,都是MIN(成员基本数据类型所占字节数的整数倍,指定对齐方式)
3)结构体总大小为结构体变量中 MIN(最大基本数据类型所占字节的整数倍,指定对齐方式的整数倍。)


首先我们要知道以下知识点:

内存大小基本单位:字节(必须要进行内存对齐)
1.地址访问:cpu 内存读写不是按照1字节1字节进行读取  以2,4,8的倍数字节块读取内存。
2. 平台在读取地址时是以偶数地址进行读取
3.不同平台 内存对齐方式不一样

4.预处理指令:
对齐方式的开始标记:#pragma pack(字节)
对齐方式的结束标记:#pragma pack()      //括号里面什么也不填
vs默认对齐方式为8,liunx默认对齐方式为4

现在我们通过代码以及运行结果举例:

#pragma pack(8)   //以8字节的方式进行内存对齐
typedef struct Student {
	char b;    //首先char占一字节   1+3
	int a;   //int占4字节   前面的1不是4的整数倍,所以前面空3个格子   4
	short c;   //short占2字节  前面相加8是2的整数倍   2+6
	long long int d;   //long long int占8字节  前面相加综合是10不是8的整数倍,所以2要加6   8
	//最后总共加起来是8的整数倍为24,结果就为24
}stu;
int main() {
	printf("%d", sizeof(stu));
}

运行结果:

24
D:\c程序\p2-2\Debug\p2-2.exe (进程 19004)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

同理我们把内存对齐方式改为4,运行结果为20。

 六、结构体的嵌套

 struct  Address{
int homeid;
const char*street;
const char*city;
}

struct  Student{
const char*name;

int age;
struct  Address address; //这里结构体计算大小的时候方法和第五点相同
int weight;
}

 七、动态内存与结构体

(一般在循环链表中用到,后面数据结构经常使用)
struct Student{
char name[10];——>const char *name
int age;
int score;
}; 
int main(){
Student s={"zs",10,100};
Student *p=(student*)malloc(sizeof(Student))
assert(p!=NULL);
memset(p,0,sizeof(Student));//将动态内存里面的值初始化为0
printf("%d",p->age);
free(p);
p=NULL;
}

八、总结(用结构体对学生成绩实行升序排序)

题目:用结构体对学生成绩实现升序排序:如果成绩相同,则按照名字进行降序排列(用到了冒泡排序)

typedef struct Student {
	const char* name;
	int score;
}stu;//定义了结构体
void temp(stu *a,stu *b) { //stu* a表示了结构体类型的指针
	stu temp = *a;
	*a = *b;
	*b = temp;
}//将数组中的元素进行了交换
int main() {
	 stu arr[] = { {"zhangzan",100},{"lisi",100},{"ww",89}};
	 int len = sizeof(arr) / sizeof(arr[0]);
	 int flag = 0;
	 for (int i = 0; i < len; i++) {//用冒泡排序的方法对成绩进行升序排列
		 flag = 0;
		 for (int j = 0; j < len - i-1; j++) {
			 if (arr[j].score > arr[j+1].score) {
				 temp(&arr[j], &arr[j + 1]);
				 flag= 1;
			 }
			 if (arr[j].name== arr[j + 1].name) {//成绩相同,对首字母进行降序排列
				 if (strcmp(arr[j].name, arr[j + 1].name) <0){
					 temp(&arr[j], &arr[j + 1]);
				}
			 }
		 }
		 if (!flag)
			 break;
	 }
	 for (int a = 0;a < len; a++) {
		 printf("%s  %d\n", arr[a].name,arr[a].score);
	 }
}

运行结果:

ww  89
zhangzan  100
lisi  100

D:\c程序\p2-2\Debug\p2-2.exe (进程 12056)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值