自定义数据类型—结构体

本文详细介绍了C语言中结构体的声明、自我引用、重命名、初始化、大小计算以及内存对齐规则。讲解了内存对齐的原因,包括平台兼容性和性能提升,并展示了如何通过修改默认对齐数来影响结构体大小。同时,文章讨论了如何在设计结构体时平衡对齐需求和空间效率,并给出了结构体参数传递的示例。
摘要由CSDN通过智能技术生成

目录

声明一个结构体类型

结构体的自我引用方式

结构体重命名

结构体变量的定义和初始化及访问

结构体大小计算

结构体的对齐规则:

 那么要为什么存在内存对齐?

那么这时候我们就要考虑一个问题:在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到哪?

结构体传参


声明一个结构体类型

 声明一个学生类型 通过学生类型来创建学生变量
描述学生:属性:名字 电话 性别 年龄

struct stu
{
	char name[20];//名字 
	char tele[12];//电话  
	char sex[10];//性别 
	int age;//年龄 
}s4,s5,s6;//全局变量 
 
struct stu s3;//全局变量 

int main()
{
	struct stu s1;
	struct stu s2;//局部变量
	
	return 0; 
}

结构体的自我引用方式

struct Node
{
	int data;
	//struct Node n;//这里是不对的 不可以在直接存放下一个结构体 
	struct Node* next;//可以存放下一个结构体的地址 
};

结构体重命名

typedef struct Node
{
	int data;
	//struct Node n;//这里是不对的 不可以在直接存放下一个结构体 
	struct Node* next;//可以存放下一个结构体的地址 
}Node;//将结构体类型重命名为Node

//struct Node s1
//Node s2
//对于创建新的结构体以上两种都是可以的

结构体变量的定义和初始化及访问

struct s
{
	char a;
	int b;
	double c;
	char arr[20];
};
 
int main()
{
	//创建结构体变量 
	struct s s1 = {'a',66,3.14,"nihao1"};
	printf("%c %d %f %s",s1.a,s1.b,s1.c,s1.arr);
	 
	return 0;
}

结构体大小计算

//结构体内存对齐
struct t1 
{
	char c1; 
	char c2;
	int a;//8字节 
};

struct t2 
{
	char c1;
	int a;
	char c2;//12字节 
};

struct t3
{
	double b;
	char c;
	int i;//16字节 
}; 

 

int main()
{
	struct t1 t1 = {0};
	printf("%d\n",sizeof(t1));//8字节
	struct t2 t2 = {0};
	printf("%d\n",sizeof(t2));//12字节
	struct t3 t3 = {0};
	printf("%d\n",sizeof(t3));//16字节
	return 0;
} 

结构体的对齐规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对        齐数 与 该成员大小的较小值。
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

对于struct t1 struct t2 struct t3来说

struct t4
{
	char c1;
	struct t3 t3;
	double d;//32字节 
};


int main()
{
	struct t4 t4 = {0};
    printf("%d\n",sizeof(t4));//32字节
    return 0;
}

 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

 那么要为什么存在内存对齐?

1. 平台原因(移植原因):

      不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2. 性能原因:

      数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

比如:对于创建的结构体s来说 我们要对整型a进行读取

struct s
{
	char c;
 	int a;
};

总体来说:结构体的内存对齐是拿空间来换取时间的做法。

因此在我们创建结构体变量时 我们可以通过修改默认对齐数  来达到我们想要的效果

比如:

1、当我们设置的默认对齐数为4时

#include <stddef.h>

#pragma pack(4)//设置默认对齐数为4 
struct s
{
	char c;//1
	//3 
	double d;//8 
};
#pragma pack()//取消设置的默认对齐数 

那么sizeof(s)就是12个字节

2、当我们设置的默认对齐数为8时

#include <stddef.h>

#pragma pack(8)//设置默认对齐数为4 
struct s
{
	char c;//1
	//7 
	double d;//8 
};
#pragma pack()//取消设置的默认对齐数 

sizeof(s)就是16个字节

那么这时候我们就要考虑一个问题:在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到哪?

答案是:

让占用空间小的成员尽量集中在一起。

比如:

struct t1 
{
	char c1; 
	char c2;
	int a;//8字节 
};

struct t2 
{
	char c1;
	int a;
	char c2;//12字节 
};

以上两个结构体存放的数据类型一样 struct t1大小为8字节 struct t2大小为12字节

结构体传参

#include <stdio.h>

//结构体传参
struct s
{
	int a;
	char c;
	double b;
};

void Init (struct s* ps)
{
	ps -> a = 10;
	ps -> c = 'q';
	ps -> b = 3.14;
}

void Print1(struct s tmp)
{
	printf("%d %c %f\n",tmp.a,tmp.c,tmp.b);
}

void Print2(const struct s* pb)
{
	printf("%d %c %f\n",pb->a,pb->c,pb->b);
}

int main()
{
	struct s s = {0};
	Init(&s);
    Print1(s);
    Print2(&s);
    
	return 0; 
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学代码的小呆鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值