首页 > 其他分享 >C语言结结结结结构体!

C语言结结结结结构体!

时间:2024-03-19 12:33:52浏览次数:16  
标签:char struct 结结 成员 C语言 位段 int 结构

P. S.:以下代码均在VS2019环境下测试,不代表所有编译器均可通过。
P. S.:测试代码均未展示头文件stdio.h的声明,使用时请自行添加。

  

结构体

一 . 结构体类型简述。


  当我们深度学习C语言后发现,储存整型可以用 “ int ” ,浮点型可以用 “ float ” “ double ”,字符型可以用 “ char ”,可每一次只能存放一个信息在变量里,且不能存放类型不同的数据。
  那如果我们要存放不同种类的信息到一个内容里,且我们可以随时得到所储存的信息,又该怎么办呢?
  这就不得不提到我们的一个老朋友兼新朋友——结构体类型。
  我们设想一个场景,对于一个学生的信息有多种,例如姓名,年龄,身高,学号。
  这时我们就可以使用结构体变量来一次性存储。(这里声明结构体类型的关键字是 “ struct ”)
  因结构体类型的初始化有多种方式,所以尽可能的展现给大家。
方式1:先定义结构体,再创建结构体变量。
struct 类型名 
{
	成员;
};
struct 类型名 变量名;
方式2:定义结构体类型时同时创建结构体变量。
struct 类型名
{
	成员;
}变量名;
方式3:通过定义匿名结构体类型再创建结构体变量。
struct 
{
	成员;
}变量名;

  这里需注意,如果在定义结构体类型时未输入结构体类型名,而直接创建结构体变量,那么这一个结构体类型就称为匿名结构体,匿名结构体类型在使用时只能使用一次,如果再次创建,则会发生错误。



二 . 结构体类型的初始化。


  在我们了解了结构体类型如何定义后,就到了初始化的环节。
  例如我们创建了一个结构体变量 Stu (代表一个学生的信息),对其中的名字,年龄,身高(cm)进行信息的初始化。
struct Stu
{
	char name[20];
	int age;
	int high;
};

  当我们想初始化时,可以有多种方式。

方式1:按结构体成员顺序进行初始化。
	struct Stu a = {"Frank" , 50 , 175 }; 
方式2:按指定成员的方式进行初始化。
	struct Stu b = {.age=28 , .high = 175 , .name="Lip"};
方式3:创建一个结构体指针和一个结构体变量,通过指针对结构体成员进行初始化。
	struct Stu c = {0};
	struct Stu * p = &c;
	p->high = 170;
	p->age = 32;


三 . 结构体成员的访问。


  对于结构体成员,我们在C语言中有两种访问方式,第一种是通过 " . "来进行访问,第二种是通过 “ -> ” 进行访问,这也是 “ -> ” 在C语言中的唯一作用了。
  而他们两个有什么区别呢?

  “ . ” 是直接对结构体变量成员进行访问,它的操作对象是结构体变量。
  “ -> ” 是对结构体指针进行操作,通过结构体指针来访问结构体的成员。

struct Stu
{
	char name[20];
	int age;
	int high;
}a = {"Frank" , 50 , 175 },*p;
	printf("%s %d %d\n",a.name,a.age,a.high);//通过点来访问
	p = &a;
	printf("%s %d %d\n",p->name,p->age,p->high);//通过指针访问

在这里插入图片描述



四 . 结构体的内存对齐。


  在了解了结构体如何定义,如何创建和初始化后,我们来思考一个问题,那就是一个结构体的大小到底是多少,每个结构体的成员都不尽相同,那它的大小又是如何计算的呢?
  让我们先看一个例子。
struct S1
{
	char c1;
	int i;
	char c2;
};
printf("%d\n", sizeof(struct S1));

  我们在不了解结构体的大小分配方式的时候,可能就直接莽着去计算了。

  哦~,char 类型一个字节,int 类型四个字节,一看大小就是6!

  让我们真实打印一下看看。

在这里插入图片描述

  怎么会是12?

  这就不得不了解一下结构体内存的对齐方式了,也就是如何存放的。

4.1. 结构体的对齐规则


  结构体的存放规则有四个,如下:

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

  2.其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。对⻬数 = 编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。(VS 中默认的值为 8 ,Linuxgcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩)

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

  4.如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

在这里插入图片描述

4.2. 嵌套结构体的大小计算。


  在上述规则的第四条,如果嵌套了结构体的情况,那又该如何计算结构体的大小?

struct S1
{
double d;
char c;
int i;
};
printf("%d\n", sizeof(struct S1));
struct S2
{
char c1;
struct S2 s;
double d;
};
printf("%d\n", sizeof(struct S2));

  这里我们创建了一个结构体S3和一个结构体S4,通过应用上面提到的规则,我们可以轻松的计算出结构体类型S1的大小为16个字节,而对于结构体类型S2里嵌套了一个结构体S1,而对齐规则4中提到嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍,通过计算可以得到,S2的大小为32。
在这里插入图片描述
  而事实也正是如此。



五. 结构体实现位段。

5.1. 什么是位段。


  1.位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他类型。

  2. 位段的成员名后边有⼀个冒号和⼀个数字。

  例如:

struct A
{
	int _a:2;
	int _b:5;
	int _c:10;
	int _d:30;
};

5.2. 位段的功能。


  位段被发明出来必然有它的作用,主要应用于根据需求来对结构体成员存放的内存进行指定大小(单位为二进制位,故称位段),主要目的是节省空间,提高效率。

5.3. 位段的内存分配。


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

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

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

  4. 在VS环境下,默认存放为从右到左存放,且如果剩余位置不够存放下一个变量,则开辟另一个需求量大小的空间继续存放。

  例如:

struct S
{
	char a:3;
	char b:4;
	char c:5;
	char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

在这里插入图片描述

  当具体存放的时候,a的值为10,二进制表示为1010,因只给a了三个比特位空间,所以会发生截断,只能存放进去010。

  b的值为12,二进制表示为1100,且存放空间足够,故储存1100,又因对结构体s最初赋值为0,故未存放位置数值就为0。

  c的值为3,二进制表示为0000 0011,且存放空间足够,故存进去00011。

  d的值为4,二进制表示为0100,且存放空间足够,故存放0100。
在这里插入图片描述

  故存放后内存中的数据应该为上图所示。

  当我们访问内存查看真实数据的时候,也会看到上图的内容(VS小端存储)。
在这里插入图片描述


  这样的存储方式真是行云流水 令人拍案!



六 . 结语 。


  十分感谢您观看我的原创文章。
  本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
  如需引用,注明地址。

标签:char,struct,结结,成员,C语言,位段,int,结构
From: https://blog.csdn.net/LiU11e/article/details/136831970

相关文章

  • 数据结构(七)并查集---以题为例
    一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。现在要进行 m 个操作,操作共有两种:Mab,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;Qab,询问编号为 a 和 b 的两个数是否在同一个集合中;输入格式第一行输入整......
  • C语言程序设计(第二版)学习笔记——第二章
    第二章算法2.1算法的概念广义的来说,为解决问题而采取的方法和步骤称为算法。针对不同的问题由不同的算法,同一问题也可以有不同的算法。计算机中算法是指计算机语言解决问题的方法和步骤。用计算机处理问题一般过程如下:(1)分析问题;(2)确定处理方案;(3)确定算法;(4)用计算机语言编写......
  • 【算法与数据结构】二叉树链式结构的实现【前中后序】
    文章目录......
  • 【C语言】猜数字游戏
    代码如下:#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>#include<stdlib.h>#include<time.h>voidgame(){ intr=rand()%100+1; intguess=0; while(1) { printf("请猜数字>:"); scanf("%d",&guess);......
  • 数据结构之BTree、B+Tree的含义及区别
    原文链接:https://blog.csdn.net/weixin_43407520/article/details/1142404381.引言前面学习索引时,了解到MySQL索引的数据类型有B+Tree索引和哈希索引,本文将详细介绍一下BTree和B+Tree的含义和他们的区别。2.BTree2.1概念B树是一种自平衡树数据结构,它维护有序数据并允许以对数时......
  • C语言wyh的物品
    题目描述wyh学长现在手里有n 个物品,这n 个物品的重量和价值都告诉你,然后现在让你从中选取k 个,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的k个物品的总价值和总重量的比值)输入描述:输入第一行一个整数T(1≤T≤10)接下来有T组测试数据,对于每......
  • 数据结构入门——二叉树(中)
    通过《二叉树(上)》的学习,我们已经对二叉树有了基本的了解,那我们现在继续深入了解二叉树。二叉树的存储结构顺序存储顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后......
  • C语言数据结构链表(无头结点)功能实现(增,删,改,查)
    #include<stdio.h>#include<stdlib.h>typedefstructLNode{   int data;   struct   LNode*next;}LNode,*LinkList; boolInitList(LinkList&L){    L=NULL;    return0; }boolinsert(LinkList&L,inti,intx){       ......
  • 数据结构318
    1.整理链栈、循环队列的代码2.猴子吃桃问题,猴子第一天摘了若干个桃,当即就吃了一半数量的桃,没吃过瘾,又多吃一个,第二天,在剩下的桃里有吃了一半数量的桃,没吃过瘾,又多吃了一个,依此类推,直到第10天,想吃桃的时候,发现只剩下一个桃了,问:猴子第一天摘了多少个桃。(递归完成)3.整理思维导......
  • 深入C语言指针,使代码更加灵活(三)
    一、函数指针1.1函数的地址在讲解函数指针变量之前,我们先思考一下什么是函数指针变量,我们可以同数组指针变量进行类比:数组指针—是指针—是存放指向数组的指针,是存放数组地址的指针;函数指针—是指针—是存放指向函数的指针,是存放函数地址的指针;数组是有地址的,那么函数......