我是靠谱客的博主 震动大碗,最近开发中收集的这篇文章主要介绍结构体(C语言)结构体的设计问题结构体的使用结构体大小结构体与动态内存的结合,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

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

结构体的设计问题

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

#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("%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<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("%sn", p->name);
	free(p);
	p = NULL;
	return 0;
}

在这里插入图片描述

最后

以上就是震动大碗为你收集整理的结构体(C语言)结构体的设计问题结构体的使用结构体大小结构体与动态内存的结合的全部内容,希望文章能够帮你解决结构体(C语言)结构体的设计问题结构体的使用结构体大小结构体与动态内存的结合所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部