栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

结构体(C语言)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

结构体(C语言)

文章目录
  • 结构体的设计问题
    • 定义一个结构体类型的数组
    • 利用 typedef 对 结构体进行重命名
    • 结构体和指针的结合
      • 结构体指针定义,解引用,指向符
    • 指针 结构体 typedef 三者结合
      • 第一种,分开定义
      • 第二种,合起来定义
  • 结构体的使用
  • 结构体大小
    • 占用内存空间问题
      • 在不考虑内存对齐的情况下:
    • 内存对齐的规则
      • 利用 #pragma pack() 来指定内存的对齐方式
  • 结构体与动态内存的结合

结构体的设计问题 定义一个结构体类型的数组
#include
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("%sn", 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 年龄:%dn", 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 年龄:%dn", 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("%sn", (*ptr).name);  //1
	printf("%dn", 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("%sn", (*ptr).name);
	printf("%dn", 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("%sn", (*ptr).name);  
	printf("%dn", 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 成绩:%dn", 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("%dn", 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("%dn", 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("%dn", 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("%dn", sizeof(B));
}

结构体与动态内存的结合
#include
#include
#include
#include
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("%sn", p->name);
	free(p);
	p = NULL;
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1037373.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号