IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】结构体详解 -> 正文阅读

[C++知识库]【C语言】结构体详解

CSDN话题挑战赛第2期
参赛话题:学习笔记

前言

阅读这篇文章,博主会带你认识、定义结构体,还会介绍如何计算结构体大小。

一.认识结构体

结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的成员

二.结构体声明

struct tag
{
 member-list;
}variable-list;

假如我们想描述一本书,如果用单一的变量我们可能无法涵盖所有的信息。
这时我们可以使用结构体。

struct book
{
 char name[20];//书名
 int date;//出版日期
 char sex[5];//类型
 char id[20];//作者
}; //分号不能丢

三.特殊的声明

3.1 不完全声明
在声明结构体的时候,可以不完全声明,比如匿名结构体类型

struct
{
	 int a;
	 char b;
	 float c;
}x;
struct
{
	 int a;
	 char b;
	 float c;
}a[20], *p;

上面两个结构在定义时省略掉了结构体标签(tag)

3.2 p = &x合法么
注意:虽然结构体内含有的变量相同,但编译器会把它们当成不同的类型,从而导致报错。因此是不合法的。

四.结构体自引用

4.1 结构体能够包含自己么

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

此时编译器会报错,为什么呢?

next是我们定义的的一个结构体变量,需要占用内存,但他的大小是多大呢?next里面又含有一个next,如果真的这样定义,next的大小会变成无穷大,因此编译失败。

那么应该如何编译呢?

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

当结构体自引用的时候,我们使用指针,因为指针的大小是确定的,因此不会出现上面的情况。

4.2 typedef
typedef可以给结构体重命名,比如

typedef struct Node
{
 int data;
}Node;

这样我们在定义结构体变量的时候,就可以使用重定义的名字,会稍微便捷一点。

struct Node num;
Node num;

五.结构体变量定义和初始化

有了前面的铺垫,那如何定义结构体变量其实很简单。

struct Point
{
 int x;
 int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2

可以声明的同时定义如p1,也可以在后面定义如p2.

//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化

赋值时成员之间用逗号隔开。

struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

当我们在在结构体中嵌套结构体时,定义时注意在{}里面再使用一个{}来给里面的结构体赋值。

六.结构体内存对齐

既然我们已经掌握了结构体的基本使用,那么应该怎么样计算结构体的大小呢?是将所有成员所占的空间相加么?显然不是的。(这是一个考点

计算结构体之前,我们需要先了解一下计算的规则。

  1. 第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
    (VS中默认的值为8)
  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
    体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

1.计算结构体大小

  • 练习1
struct S1
{
	 char c1;
	 int i;
	 char c2;
};
printf("%d\n", sizeof(struct S1));

运行结果:
在这里插入图片描述我们画个图来解释这个题:

在这里插入图片描述第一个元素对齐偏移量为0的地址处,char类型占据一个字节,i为int类型,大小为4小于VS默认值8,因此i对齐4,又因为整体大小需要占据最大对齐数(这道题为4)的整数倍处,因此大小为12.

  • 练习2.
struct S3
{
	double d;
	char c;
	int i;
};
struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct S4));

运行结果:
在这里插入图片描述依旧用一个图来解释:

在这里插入图片描述用练习1的方法我们能轻易地算出S3的大小是16,S3里的最大对齐数是8,因此S3对齐到8的位址,d对齐到24的位址,加起来为32是最大对齐数8的倍数。

由此我们还能得出一个结论:
将较小的变量放在一起定义会比较节省空间。

七·.修改对齐数

#pragma pack(1)//设置默认对齐数为1
struct S2
{
 char c1;
 int i;
 char c2;
};

运行结果:
在这里插入图片描述

八.结构体传参

我们都知道函数传参既能传值又能传址,那么当我们想要传递结构体的时候我们应该传哪一种呢?

函数传参的时候,参数需要压栈,会有时间和空间上的系统开销
如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。因此最好传址

最后

如果你觉得博主写的还不错的话,记得点赞收藏加关注,感谢支持!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:08:17  更:2022-09-21 00:09:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 12:53:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码