自定义类型:结构体-1

简介: 自定义类型:结构体

前言:

类型

1、内置类型

char

short

int

long

long long

double

2、自定义类型

当内置类型不能够满足需求的时候,支持自定义一些类型

1>结构体

2>枚举

3>联合体


一. 结构体类型的声明

1.1 结构体的概念

结构体是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

1.2 结构体的声明

举例描述⼀个学⽣:

struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}s3,s4;//全局变量
int  main()
{
struct Stu s1 ,s2;//局部变量
return 0;
}

1.3  特殊的声明

在声明结构的时候,可以不完全的声明。

⽐如:

//匿名结构体类型
struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
} *p;

上⾯的两个结构在声明的时候省略掉了结构体标签(tag)。

那么问题来了?

//在上⾯代码的基础上,下⾯的代码合法吗?
p = &x;

解析:不合法,会出现警告: 编译器会把上⾯的两个声明当成完全不同的两个类型,所以是⾮法的。


注:匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。

1.4 结构体的初始化

struct Stu
{
char name[20];//名字
int age;//年龄
float score;//成绩
}s3,s4;//全局变量
int  main()
{
struct Stu s1 ={"zhangsan",20,98.5f};
struct Stu s2={.age=22,.name="lisi",.score=93.0f};
return 0;
}

1.5  结构的自引用

5f54d3e3c52ad5e3925126c9bae5d122_ee4d7f4db30a458cbed929277acf9cf3.png


以上链表中存储1的结构叫一个节点。

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

⽐如,定义⼀个链表的节点:

struct Node
{
 int data;
 struct Node next;
};

上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?

仔细分析,其实是不⾏的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤⼩就会⽆穷的⼤,是不合理的。

正确的⾃引⽤⽅式:

struct Node
{
int data;
struct Node* next;//下一个节点的地址
};

sizeof(stcurt Node)大小就可以计算了


在结构体⾃引⽤使⽤的过程中,夹杂了typedef对匿名结构体类型重命名,也容易引⼊问题,看看下⾯的代码,可⾏吗?

typedef struct
{
int data;
Node* next;
}Node;

答案是不⾏的,因为Node是对前⾯的匿名结构体类型的重命名产⽣的,但是在匿名结构体内部提前使⽤Node类型来创建成员变量,这是不⾏的。

解决⽅案如下:定义结构体不要使⽤匿名结构体了

typedef struct Node
{
int data;
struct Node* next;
}Node;


二. 结构体内存对⻬

我们已经掌握了结构体的基本使⽤了。

现在我们深⼊讨论⼀个问题:计算结构体的⼤⼩。

这也是⼀个特别热⻔的考点: 结构体内存对⻬

下面我们看这样一个例子

struct S1
{
  char c1;
  int i;
  char c2;
};
struct S2
{
  char c1;
  char c2;
  int i;
};
int main()
{
  struct S1 s1 = { 'a',100, 'b'};
  struct S2 s2 = { 'a','b','100' };
  printf("%zd\n", sizeof(s1));
  printf("%zd\n", sizeof(s2));
  return 0;
}

这俩个结构变量类型和数据一样,只是顺序不一样,那么大小会一样码?


输出:


a1c83a2bd97212ab6d27dca2f8f6675d_af060c9a3fce4847a9597c8632f645c1.png


我们发现大小不同,它们是如何分配空间的呢?

这就涉及到内存对齐!

2.1  对齐规则

首先先得掌握结构体的对齐规则:

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

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

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

- VS中默认的值为8

- Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩

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

整数倍。

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

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

由对齐规则对上面程序分析有:

f008466f51c1391df8d100183964c790_06692ccd781148159302ef96c8900225.png


02b8f4c211ed150e3d87922aa786b67a_2968cb7630a14babac63d0c415967e52.png


2.11 练习1

struct S3
{
double d;
char c;
int i;
};
int main()
{
printf("%d\n", sizeof(struct S3));
return 0;
}

解析:根据分析可知,double的对齐数 8,char对齐数 1,int 对齐数 4,首先double放8个字节,紧接连续放char,此时地址到8了,下一个地址位9,9不是4的倍数,所以放在地址12,放四个字节。共16个字节,16是结构体最大对齐数8的倍数,所以答案是16


输出:  0c1b8ea3930e8602ef5b5b7ddedc4e6d_490b0e557c10471c9f8a9fd2be9cedd9.png


相关文章
|
10月前
|
存储 数据挖掘 数据处理
2600 万表流计算分析如何做到? 时序数据库 TDengine 助力数百家超市智能化转型
在生鲜超市的高效运营中,实时数据分析至关重要。万象云鼎的“云鲜生”通过智能秤+网关+软件系统的组合,实现了销售数据的精准管理与优化。而在数据处理方面,TDengine 的流计算能力成为了这一方案的核心支撑。本文详细分享了“云鲜生”如何利用 TDengine 高效存储和分析海量销售数据,在优化超市运营、提升用户体验的同时,解决高基数分组、高并发查询等技术挑战。
289 1
|
9月前
|
存储 机器学习/深度学习 人工智能
Elasticsearch:使用阿里云 AI 服务进行向量化和重新排名
本文介绍了如何将阿里云 AI 功能与 Elasticsearch 集成,以提高语义搜索的相关性。
616 0
|
Windows
开源批量卸载工具
【10月更文挑战第5天】
546 2
|
SQL 分布式计算 数据处理
Structured Streaming和Flink实时计算框架的对比
本文对比了Structured Streaming和Flink两大流处理框架。Structured Streaming基于Spark SQL,具有良好的可扩展性和容错性,支持多种数据源和输出格式。Flink则以低延迟、高吞吐和一致性著称,适合毫秒级的流处理任务。文章详细分析了两者在编程模型、窗口操作、写入模式、时间语义、API和库、状态管理和生态系统等方面的优劣势。
|
数据挖掘 数据处理 C++
Pandas VS Polars:迅如闪电的全新体验
Pandas VS Polars:迅如闪电的全新体验
392 1
|
SQL Java 数据库连接
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。
|
监控 数据可视化 调度
ERP系统中的生产排程与生产效率分析解析
【7月更文挑战第25天】 ERP系统中的生产排程与生产效率分析解析
491 0
WAT测试介绍
本文只要介绍芯片WAT的测试环境,测试结构,测试机台,测试标准,测试项目以及测试的意义。
WAT测试介绍
|
计算机视觉
人脸比对实现判断并查找面部特征
compare_faces( ) compare_faces( known_face_encodings, face_encoding_to_check, tolerance=0.6 ) 比较脸部编码列表和候选编码,看看它们是否匹配。 参数: known_face_encodings:已知的人脸编码列表 face_encoding_to_check:待进行对比的单张人脸编码数据 tolerance:两张脸之间有多少距离才算匹配。该值越小对比越严格,0.6是典型的最佳值。 返回值: 一个 True或者False值的列表,该表指示了known_face_encodings列表的每个成员的匹
582 1
|
自然语言处理
【ELK】(三)Elasticsearch 安装IK中文分词器
【ELK】(三)Elasticsearch 安装IK中文分词器
568 0
【ELK】(三)Elasticsearch 安装IK中文分词器

热门文章

最新文章