结构体(C语言)

结构体的设计问题

定义一个结构体类型的数组

#include<stdio.h>
struct Student{
	const char* name;
	int age;
	int score;
};

int main() {
	//定义结构体变量
	struct Student stu1 = { "zs",10,100 };
	struct Student stu2;
	stu2 = { "ls",12,98 };
	//通过结构体变量来进行成员的访问  .(点,成员访问符)
	printf("%s\n", stu1.name);

	//定义一个结构体类型的数组,赋值,数组打印:第...个学生姓名,年龄,成绩
	struct Student arr[] = { {"zs",10,100},{"ls",12,98} };
	int len = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < len; i++) {
		printf("第%d个学生:姓名:%s 年龄:%d\n", i + 1, arr[i].name, arr[i].age);
	}
	struct Student brr[] = { stu1,stu2,{"wmz",9,89} };//上面已经定义过 stu1,stu2,可直接引用到数组中
	for (int i = 0; i < len; i++) {
		printf("第%d个学生:姓名:%s 年龄:%d\n", i + 1, arr[i].name, arr[i].age);
	}
}

在这里插入图片描述

利用 typedef 对 结构体进行重命名

利用 typedef 对 struct Student(结构体) 进行重命名,使得C与C++不需修改都可使用
分开写为:

struct Student{
	const char* name;
	int age;
	int score;
};
typedef struct Student Student;

也可合起来写:

typedef struct Student{
	const char* name;
	int age;
	int score;
}Student;
int main(){
    Student s={"zs",10,100};
}

结构体和指针的结合

结构体指针定义,解引用,指向符

typedef struct Student {
	const char* name;
	int age;
	int score;
}Student;
int main() {
	Student s = { "zs",10,100 };
	Student* ptr = &s;
	printf("%s\n", (*ptr).name);  //1
	printf("%d\n", ptr -> age);   //2      1,2效果相同     ->指向符(具有解引用的功能)
}

在这里插入图片描述

解引用的优先级比点结构体体访问符的优先级低,所以要给解引用加上括号,也可通过 指向符 来进行解引用

指针 结构体 typedef 三者结合

第一种,分开定义

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

第二种,合起来定义

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

结构体的使用

按照学生成绩对学生数组进行冒泡排序降序
若成绩相同,按照姓名进行冒泡排序(降序)

typedef struct Student {
	const char* name;
	int age;
	int score;
}Student, * Pstu;

typedef Student Elemtype;

void Swap(Elemtype* a, Elemtype* b) {
	Elemtype t = *b;
	*b = *a;
	*a = t;
}
//冒泡
void SBubbleSort(Elemtype* arr, int len) {
	for (int i = 0; i < len; i++) {
		int flag = 0;
		for (int j = 0; j < len - 1 - i; j++) {
			if (arr[j].score < arr[j + 1].score) {
				Swap(&arr[j], &arr[j + 1]);
				flag = 1;
			}
			else if (arr[j].score == arr[j + 1].score) {
				if (strcmp(arr[j].name, arr[j + 1].name) < 0) {
					Swap(&arr[j], &arr[j + 1]);
				}
			}
		}
		if (!flag) {
			break;
		}
	}
}

int main() {
	Student arr[] = { {"zs",10,100},{"ls",9,100} ,{"wmz",10,98} };
	int len = sizeof(arr) / sizeof(arr[0]);
	SBubbleSort(arr, len);
	for (int s = 0; s < len; s++) {
		printf("第%d名:姓名:%s 年龄:%d 成绩:%d\n", s+1, arr[s].name,arr[s].age,arr[s].score);
	}
	return 0;
}

在这里插入图片描述

结构体大小

1.地址访问:CPU 内存读写不是按照1字节1字节读取,我们可以设定根据 2,4,8 的倍数的字节块读取内存。
2.平台读取地址,偶数地址读取
3.不同平台内存对齐方式不同

占用内存空间问题

在不考虑内存对齐的情况下:

struct Student{
	const char name[10];
	int age;
	int score;
};
struct Stdent stu = { "zs",10,100 };


上述代码stu占用十八个字节

struct Student{
	const char* name;
	int age;
	int score;
};
struct Stdent stu = { "zs",10,100 };

在这里插入图片描述
上述代码*const char name;占用四个字节(根据平台而异),所以stu占用十二个字节

内存对齐的规则

注:MIN表示两者中最小的一个
1)变量首地址,必须是 MIN(结构体最大基本类型数据,指定对齐方式)所占字节的整数倍
2)每个成员变量相对于结构体首地址的偏移量,都是 MIN(该成员基本数据类型,指定对齐方式)所占字节的整数倍
3)结构体总大小为MIN(结构体最大数据类型(结构体内有嵌套结构体,应为所有结构体的最大数据类型),指定对齐方式)所占字节对的整数倍
4)vs 上默认对齐方式为 8 个字节,Linux上默认对齐方式为 4 个字节

例如:

struct Student {
    int a;
    char b;
    short c;
    long long d;
};
struct Student s = { 1,'a',1,10L };
int main() {
    printf("%d\n", sizeof(Student));
}

在这里插入图片描述
在这里插入图片描述
如图,该结构体占 4+1+1+2+8=16 个字节

利用 #pragma pack() 来指定内存的对齐方式

#pragma pack(字节) 对齐方式开始 预处理指令
#pragma pack() 对齐方式结束 预处理指令

例如:

#pragma pack(8)
struct Student {
    int a;  //4
    char b;  //1+1
    short c;  //2
    long long d; //8
    char e;  //1+7
};
#pragma pack()
int main() {
    printf("%d\n", sizeof(Student));
}

在这里插入图片描述

#pragma pack(4)
struct Student {
    int a;  //4
    char b;  //1+1
    short c;  //2
    long long d; //8
    char e;  //1+3
};
#pragma pack()
int main() {
    printf("%d\n", sizeof(Student));
}

在这里插入图片描述

struct A {
    long long a;//8
    short b;//2+6
};
struct B {
    struct A add;//16
    int c;//4+4
};
#pragma pack()
int main() {
    printf("%d\n", sizeof(B));
}

在这里插入图片描述

结构体与动态内存的结合

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
typedef struct Student {
	const char* name;
	int age;
}Stu;
int main() {
	Stu s = { "zd",12 };
	Stu* p = (Stu*)malloc(sizeof(Stu));
	assert(p != NULL);
	memset(p, 0, sizeof(Stu));
	printf("%s\n", p->name);
	free(p);
	p = NULL;
	return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值