结构体以及引申

欢迎来到本期频道!

想要了解结构体吗?想知道如何使用结构体吗?满足你!(大佬请忽略)

为了能够更灵活地描述对象,C语言提供了结构体类型.

一:结构体的初阶认识

1.什么是结构体(struct)

C语言中,结构体是一种数据类型,结构体类型属于自定义类型,结构体类型的成员变量可以是不同类型。

2.如何创建结构体类型

结构体类型可以用来描述一个复杂对象,例如描述一个学生:
一般情况下:

struct stu
{
	int num[10];
	char name[10];
	int age;
	//......
};

一些特殊情况下,会创建匿名结构体:

struct 
{
	char d;
	short e;
	int f;
}s;			//s是一个该结构体类型变量

注意:结构体类型不能嵌套自身,因为无法定义,是不合法的。例如:

struct k
{
	int a;
	struct k u;
};

3.如何创建和使用结构体变量


	struct stu s1={20220190,"张三",66};	//创建一个struct stu类型的变量并初始化
	struct stu s2={.num=20210273,.age=38,.name="王五"};	//另一种初始化方式


	struct stu *p=&s2;
	printf("%s\n",s1.name);
	printf("%d\n",p->age);

二:结构体的进阶认识

由于平台原因和性能原因,结构体需按对齐规则来存放,这是一种以空间换时间的做法。

1.结构体的内存对齐规则

①结构体成员的第一个变量对齐到结构体起始位置偏移量为0的地址。

②其它的成员变量对齐到偏移量为对齐数整数倍的位置。
该对齐数为编译器默认对齐数和该成员变量自身大小(如果是数组,取数组元素的大小)的最小值。
在vs2019中,这里的默认对齐数是可以修改的:
#pragma pack (n)
默认对齐数改为n

③结构体的总大小是最大对齐数 (所有成员的对齐数比较) 的整数倍。

④如果嵌套了结构体,当计算最大对齐数时,该结构体变量的所有成员的对齐数都要参与比较。

根据该规则,我们就可以分析结构体大小了,例如:
在这里插入图片描述

2.结构体传参

#include<stdio.h>
	struct grade
	{
		char name[10];
		int Math;
		int English;
		int Chinese;
	};
	
	int total1(struct grade s)				//传值
	{
		return s.Math + s.English + s.Chinese;
	}
	
	int total2(struct grade* s)				//传址
	{
		return s->Math + s->English + s->Chinese;
	}
	
	int main()
	{
		struct grade a = { "张三", 60, 59, 38 };
		struct grade b = { "李四", 57, 50, 66 };
		int ret1 = total1(a);
		int ret2 = total2(&b);
		return 0;
	}

两种方式都能达到想要的功能,但是哪种方式效率更高呢?显然是传址,因为传址只需创建一个指针变量,而传值要创建一个结构体变量,如果结构体变量特别大,那在传参时会有很大的时间和空间上的系统开销。所以尽量使用传址传参。

三:结构体的引申

1.位段

C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域。

位段是专门用来节省空间的,但有跨平台问题。
特点: ①位段的成员必须是int,unsigned int,signed int,char类型。

②位段成员后有一个冒号和一个数字。

位段的创建:

struct p
{
	char a : 2;
	char b : 3;
	char c : 4;
};

位段成员的访问和结构体是一样的,这里就不细说了。
位段的内存分配
以上述所建类型为例:
在这里插入图片描述
位段的注意事项:
①int类型位段被当成有符号还是无符号是不确定的。

②位段中的最大位的数目不能确定。(例如32位和16位机器上的位数就不同,不能跨平台)

③位段中的成员在内存中从左向右,还是从右向左分配,没有明确规定。

④当一个结构包含两个位段,第二个位段成员较大,剩余的位无法容纳时,是浪费还是继续使用,没有明确规定。

⑤对位段成员不能取地址操作。(bit位没有地址)

2.柔性数组

在c99中,结构中的最后一个成员允许是未知大小的数组,这个就是柔性数组成员。

在结构体中只能有一个柔性数组成员,该成员必须是结构体的最后一个成员。

例如:

struct s
{
	int a;
	int arr[];		//或者arr[0]   柔性数组成员
}

柔性数组特点:
①结构中,柔性数组成员前面必须至少有一个其它成员。

②sizeof返回此结构的大小不包含柔性数组的内存。

③包含柔性数组成员的结构体用malloc函数动态分配内存,并且分配的内存应大于结构体的大小,以适应柔性数组的预期大小。

我们利用这些特点来使用柔性数组:

#include<stdio.h>
#include<stdlib.h>
struct stu
{
	char name[5];
	int  grade[];
};
int main()
{
	void* p = malloc(sizeof(struct stu) + 10*sizeof(int));		//根据需要开辟空间
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	
	struct stu *person = (struct stu*)p;
	int i = 0;
	for (i = 0; i < 10; i++)					//使用为柔性数组开辟的空间
	{
		person->grade[i] = 57+i;
		printf("%d ", person->grade[i]);
	}

	free(p);
	p = NULL;
	return 0;
}

除此之外,我们还可以 模拟 柔性数组:

#include<stdio.h>
#include<stdlib.h>
struct s
{
	char name[5];
	int* grade;
};
int main()
{
	struct s stu = { "老王" };
	
	void* t1 = malloc(10 * sizeof(int));
	if (t1 == NULL)
	{
		perror("malloc");
		return 1;
	}
	
	stu.grade = (int*)t1;
	int i = 0;
	for (i = 1; i < 10; i++)
	{
		stu.grade[i] = 57 + i;
		printf("%d ", stu.grade[i]);
	}
	
	free(t1);
	t1 = NULL;
	return 0;
}
本期分享就到这里了,希望能够让你更热爱C语言。
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言中的结构体是一种用户自定义的数据类型,它可以包含多个不同类型的数据成员。结构体定义了一种数据结构,可以将多个相关的数据封装在一个结构体变量中。 结构体的定义以关键字struct开始,之后是结构体的名称,紧接着是一对大括号{},在大括号中定义了结构体的数据成员。每个数据成员都有一个类型和一个名称,可以通过"."操作符来访问结构体中的成员。 函数是一段可以重复调用的代码块,它接受输入参数,执行特定的任务,并返回结果。在C语言中,函数可以在全局作用域中定义,也可以在其他函数内部定义。函数的定义以返回类型开始,之后是函数名和参数列表,然后是函数体。 在给定的引用中,第一个引用讨论了结构体成员的地址和赋值的问题。结构体的成员是独立的,修改一个成员的值不会影响其他成员的值。第二个引用和第三个引用展示了如何使用printf函数输出结构体的成员。 综上所述,C语言中的结构体是一种用户自定义的数据类型,它可以包含多个不同类型的数据成员。函数是一段可以重复调用的代码块。在C语言中,结构体和函数都是非常重要的概念,用于组织和操作数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C语言基础:C语言结构体(6) - 结构体与函数](https://blog.csdn.net/weixin_35433448/article/details/117140521)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值