前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【 结构体 】详解

【 结构体 】详解

作者头像
叫我龙翔
发布2024-01-30 13:55:06
1060
发布2024-01-30 13:55:06
举报
文章被收录于专栏:就业 C++ 综合学习

结构体

问题引入

假如有一群人的“身高”和“姓名”,需要按照“身高”排序

代码语言:javascript
复制
   在不使用结构体的情况下:我们自然而然想到使用数组进行分别存储“身高”和“姓名”,然后进行sort排序。	代码如下:
代码语言:javascript
复制
#include<stdio.h>
#include<ctype.h>

#define NUM 4      //学生人数
#define NAME_LEN 64//名字最大字符数

void swap_highth(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}
void swap_str(char* a, char* b)
{
	char tmp[NAME_LEN] = { 0 };
	strcpy(tmp, a);
	strcpy(a, b);
	strcpy(b, tmp);
}
void sort(char name[][NAME_LEN], int highth[])
{
	int i = 0, j = 0;
	for (i = 0; i < NUM-1; i++)
	{
		for (j = 0; j <NUM-1-i; j++)
		{
			if (highth[j-1] > highth[j])
			{
				swap_highth(&highth[j-1], &highth[j ]);
				swap_str(name[j-1], name[j ]);
			}
		}
	}
}
int main()
{
	char name[][NAME_LEN] = {"liming" ,"zhangsan", "lisi" , "wangwu"};
	int highth[] = {170,175,168,180};

	for (int i = 0; i < NUM; i++)
	{
		printf("%s: %d \n", name[i], highth[i]);
	}

	sort(name, highth);
	puts("按身高排序:\n");
	for (int i = 0; i < NUM; i++)
	{
		printf("%s: %d \n", name[i], highth[i]);
	}

	return 0;
}

肉眼可见的非常复杂,不仅要按”身高“进行排序还要将对应的”姓名“也进行排序,如果再增加“奖学金”,“成绩”等数据之后将更复杂。那么有没有其他解决办法呢。

结构体

这时结构体应运而生,结构体是用来储存不同类型的集合,就像名片一样,展示一个人的不同信息。而上面提到的排序问题就可以通过结构体来进行解决,现在让我们开始学习结果体。

结构体声明与创建

结构体的声明:

通过这样的声明就可以创建结构体变量,而这个结构体的类型是“struct student”。(如果我们不输入“student”,就会产生匿名结构体,匿名结构体只能使用一次。) 这样我们就建立了“名片”

下一步便是进行数据的输入。

结构体初始化

我们依次输入对应数据即可。 然后我们看如何访问结构体数据

结构体访问

结构成员访问操作符有两个⼀个是“ . ” ,⼀个是 “-> ”. 它们的使用分别是: 结构体变量 . 成员变量名 结构体指针 —> 成员变量名

一般引用结构体数据使用“.”,输入结构体数据使用“—>”。 一定注意使用的数据类型。

结构体的自引用

在结构中包含⼀个类型为该结构本⾝的成员是否可以呢?比如:

这样是一个正确的自引用方式,即产生链表的节点。 当然在自引用中不可以使用匿名结构体。

结构体内存对齐

这是结构体最难的一部分知识 对齐规则:

  1. 结构体的第⼀个成员对⻬到相对结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。 对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
  • VS中默认的值为8(可以通过#pragma pack( N )进行修改)
  • Linux中没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
  1. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍。
  2. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
以我们刚才创建的结构体为例:

这是其在内存中的空间。

这个比较特别,没有造成浪费空间。 下面再看一个例子:

这是其在内存中的空间。

发现其中有浪费空间,这是为什么?

原因有:
  1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常。
  2. 性能原因: 数据结构(尤其是栈)应该尽可能地在⾃然边界上对⻬。原因在于,为了访问未对⻬的内存,处理器需要 作两次内存访问;⽽对⻬的内存访问仅需要⼀次访问。假设⼀个处理器总是从内存中取8个字节,则地 址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数,那么就可以 ⽤⼀个内存操作来读或者写值了。否则,我们可能需要执⾏两次内存访问,因为对象可能被分放在两 个8字节内存块中。 总体来说:结构体的内存对⻬是拿空间来换取时间的做法。
我们如何避免浪费较大空间

尽量让占⽤空间⼩的成员尽量集中在⼀起(根据对齐规则不难发现这个道理)

排序问题结构体解法

回到开头的问题,用结构体是不是可以更方便解决问题了呢。

代码语言:javascript
复制
#include<stdio.h>

#define NUM 4
#define NAME_LEN 64
struct stu
{
	char name[NAME_LEN];
	int highth;
	int score;
};
void swap(struct stu* num1, struct stu* num2)
{
	struct stu tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}
void sort(struct stu arr[], int n)
{
	int i = 0, j = 0;
	for (i = 0; i < n - 1; i++)
	{
		for (j = 0; j < n - 1 - i; j++)
		{
			if (arr[j - 1].highth > arr[j].highth)
			{
				swap(&arr[j - 1], &arr[j]);
			}
		}
	}
}
int main()
{
	struct stu arr[] = { 
		                 {"liming",170,50},
	                     { "zhansan",175,60 },
	                     { "lisi",168,100 },
	                     { "wangwu",180,80 } 
	                   };

	int i = 0;
	for (i = 0; i < NUM; i++)
	{
		printf("%s: %d ___%d\n", arr[i].name,arr[i].highth,arr[i].score);
	}

	sort(arr, NUM);
	puts("按身高排序后\n");
	for (i = 0; i < NUM; i++)
	{
		printf("%s: %d ___%d\n", arr[i].name, arr[i].highth, arr[i].score);
	}
	return 0;
}

可以看见,无论结构体中有多少变量,只需要一次交换即可,提高效率。

结构体的讲解到此结束。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 结构体
    • 问题引入
      • 结构体
        • 结构体声明与创建
        • 结构体初始化
        • 结构体访问
        • 结构体的自引用
        • 结构体内存对齐
        • 排序问题结构体解法
        • 结构体的讲解到此结束。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档