首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C语言结构体

C语言结构体

作者头像
用户11971916
发布2025-12-30 15:40:15
发布2025-12-30 15:40:15
220
举报

1.什么是结构体?

结构体就像集合,里面可以存放不同的数据类型,如: 标量、数组、指针,甚⾄是其他结构体。

2.结构体的声明

代码语言:javascript
复制
int main()
{
	struct stu
	{//创建一个学生的结构体
		char name[20];//名字
		int age;//年龄
		char sex[2];//性别
		char id[10];//学号
	};
}

结构体的直接访问

代码语言:javascript
复制
int main()
{
	struct s
	{
		int x;
		int y;
	}p = {1,2};
	printf("%d %d", p.x, p.y);
}

结构体的间接访问

代码语言:javascript
复制
int main()
{
	struct s
	{
		int x;
		int y;
	}p = {1,2};
	struct s* pp = &p;
	printf("%d %d", pp->x, pp->y);
}

结构体的自引用

代码语言:javascript
复制
struct s
{
	int x;
	struct x y;
}

这种结构体自引用是不正确的,会导致变量大小变得无穷大。

代码语言:javascript
复制
struct s
{
	int x;
	struct x* y;
}

以上正确代码

在结构体⾃引⽤使⽤的过程中,夹杂了 typedef 对匿名结构体类型重命名,也容易引⼊问题

代码语言:javascript
复制
int main()
{
	typedef struct
	{
		int x;
		p* y;
	}p;
}

定义结构体不要使⽤匿名结构体

代码语言:javascript
复制
int main()
{
	typedef struct p
	{
		int x;
		struct p* y;
	}p;
}

以上正确代码

3.结构体内存对齐

1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处

2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。

3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的

整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构

体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

我们可以修改默认对其书数

代码语言:javascript
复制
int main()
{
//#pragma pack(1)
	struct S1
	{
		char c1;
		int i;
		char c2;
	};
	printf("%d\n", sizeof(struct S1));
}

#pragma 这个预处理指令,可以改变编译器的默认对⻬数

代码语言:javascript
复制
int main()
{
#pragma pack(1)
	struct S1
	{
		char c1;
		int i;
		char c2;
	};
	printf("%d\n", sizeof(struct S1));
}

4.结构体的传参

代码语言:javascript
复制
struct S
{
	int x[10];
	int y;
};
void print1(struct S s)
{
	printf("%d\n", s.y);
}
void print2(struct S* s)
{
	printf("%d\n", s->y);
}
int main()
{
	
	struct S s = { {1,2,3,4,5},10 };
	print1(s);
	print2(&s);
}

以上的代码print2是比print1要好的

因为函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。

如果传递⼀个结构体对象的时候,结构体过⼤,参数压栈的的系统开销⽐较⼤,所以会导致性能的下 降。

5.结构体的位段

代码语言:javascript
复制
struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};
int main()
{
	printf("%d\n", sizeof(struct A));
	return 0;
}

A是结构体位段类型

那位段A所占内存的⼤⼩是多少?、

为什么是8?

位段的内存分配

代码语言:javascript
复制
struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

int main()
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	return 0;
}

1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的⽅式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。

位段注意事项

位段的⼏个成员共有同⼀个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位 置处是没有地址的。

所以不能对位段的成员使⽤&操作符,这样就不能使⽤scanf直接给位段的成员输⼊值,只能是先输⼊ 放在⼀个变量中,然后赋值给位段的成员。

代码语言:javascript
复制
struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};
int main()
{
	struct A sa = { 0 };
	scanf("%d", &sa._b);//这是错误的

	//正确的⽰范
	int b = 0;
	scanf("%d", &b);
	sa._b = b;
	return 0;
}

如有错误,请指正。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档