C语言自定义类型-结构体

2023-11-13

一,结构体声明

C语言中为我们准备了许多现成的数据类型例如:
int
short
float
double
char
long
long long

等等. . . . . .
但是我们描述一些复杂的事物,光靠上述的数据类型是描述不清的,例如,我们描述一个大学生,可以描述他的身高,年龄,学号等等。

那么结构体类型是如何生命的呢?

struct Stu
{
	int hight;
	char num[20];
	int age;
};

注意: 大括号后面的分号不能丢哦。

二,特殊结构体声明

结构体在声明的时候,可以不完全声明,像下面一样。

struct 
{
	int a;
	int b;
	char c;
}x;
struct
{
	int a;
	int b;
	char c;
}b,*p;

但是,当不完全声明的时候,我们可以将x变量的地址,存到p指针当中吗?

p = &x;

在这里插入图片描述
可以看到,是不可以的,虽然两个结构体变量的各个成员相同,但是编译器仍然认为这是两个不同的结构体。

并且不完全声明的结构体,不能再用来定义新的变量例如下面

struct
{
	int a;
	int b;
	char c;
};
int main()
{
	
	struct x;
	return 0;
}

在这里插入图片描述
不完全声明的结构体如果想定义变量,只能在声明的同时定义变量例如下面

struct 
{
	int a;
	int b;
	char c;
}x;
struct
{
	int a;
	int b;
	char c;
}b,*p;

三,结构体自引用

我们先看几行代码

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

这样的代码,可行吗?

如果可行的话?那sizeof(struct Node)是多少呢?

我们可以看出结构体在不断的嵌套你中有我,我中有你,不断地这样下去,想必肯定是错误的。
实现结构体自引用的正确的方法如下:

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

四,结构体变量的定义与初始化

1,在结构体声明的同时初始化

struct stu
{
	int age;
	int hight;
	char num[20];
}ss1;

2,在结构体声明后定义

int main()
{
	struct stu ss2;
	return 0;
}

3,按照结构体成员顺序初始化

int main()
{
	struct stu ss2 = { 19,182,"47385782" };
	return 0;
}

4,不按照成员顺序初始化

int main()
{
	
	struct stu ss3 = { .hight = 183,.num = "42345235",.age = 22 };

	return 0;
}

五,结构体内存对齐

我们先看一段代码

struct a
{
	char c1;
	int i;
	char c2;
};
struct b
{
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct a));
	printf("%d\n", sizeof(struct b));
	return 0;
}

你想一下,答案是什么呢?

在这里插入图片描述

可能有人会想,这两个的答案不应该都是6吗?
首先,我们先介绍一个宏:offsetof
在这里插入图片描述
他的返回值是,结构体成员相对于结构体变量的偏移量
例如:

struct a
{
	char c1;
	int i;
	char c2;
};
#include<stddef.h>
int main()
{
	printf("%d\n", offsetof(struct a, c1));
	printf("%d\n", offsetof(struct a,i));
	printf("%d\n", offsetof(struct a, c2));
	return 0;
}

在这里插入图片描述
在这里插入图片描述

可以看到根据offsetof的返回值,画出的图是上述那样的,结构体变量的大小应该是9个字节大小啊。
下面我们就来介绍一下,结构体内存对齐的规则

规则:
(1)结构体变量的第一个成员永远放在相对于结构体变量偏移量为0 的位置。
(2)其他成员放在偏移量为其对齐数整数倍的位置处
对齐数:为默认对齐数和结构体成员大小的较小值
vs:默认对齐数 8
Linux:不设置默认对齐数
(3)结构体变量的总大小为最大对齐数的整数倍
(4)如果嵌套了结构体的情况,嵌套的结构体对齐到自己最大对齐数的整数倍处,
结构体的总大小为最大对齐数的整数倍(包括嵌套结构体中的对齐数)

下面,针对第四条写一段代码

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

那么这个结构体的总大小是多少呢?
在这里插入图片描述
答案是24,你想对了吗?

六,修改默认对齐数

可以用#pragma pack()来改变默认对齐数

#pragma pack(4)//改变默认对齐数为4
 
#pragma pack()//回复默认对齐数

七,结构体传参

传参有两种方式
(1)传值

struct STU
{
	int age;
	int hight;
	char num[20];
};
void print1(struct STU s)
{
	printf("%d\n", s.age);
	printf("%d\n", s.hight);
	printf("%s\n", s.num);

}
int main()
{
	struct STU ss1 = { 19,182,"154235265" };
	print1(ss1);
	return 0;
}

(2)传址

void print2(struct STU* s)
{
	printf("%d\n", s->age);
	printf("%d\n", s->hight);
	printf("%s\n", s->num);
}
int main()
{
	struct STU ss1 = { 19,182,"154235265" };
	print1(ss1);
	print2(&ss1);
	return 0;
}

我们知道形参是实参的一份临时拷贝,会开辟新的空间,如果当我们的结构体较大的时候,利用传值的传参方式会很浪费空间,所以结构体传参的时候采用传址调用比较好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言自定义类型-结构体 的相关文章

  • 为什么libc++的shared_ptr实现使用完整内存屏障而不是宽松内存屏障?

    在boost的实现中shared ptr 它用放松内存排序以增加其引用计数 https github com boostorg smart ptr blob master include boost smart ptr detail sp
  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • 迭代变量并查找特定类型实例的技术

    我想迭代进程中内存中的变量 通过插件动态加载 并查找特定类型的实例 以前我可以找到特定类型 或内存中的所有类型 我可以创建类型的实例 我可以获取作为不同类型的字段包含的实例 但我无论如何都不知道只是 搜索 特定类型的实例 一种方法是使用 W
  • 我的线程图像生成应用程序如何将其数据传输到 GUI?

    Mandelbrot 生成器的缓慢多精度实现 线程化 使用 POSIX 线程 Gtk 图形用户界面 我有点失落了 这是我第一次尝试编写线程程序 我实际上并没有尝试转换它的单线程版本 只是尝试实现基本框架 到目前为止它是如何工作的简要描述 M
  • 使用具有现有访问令牌的 Google API .NET 客户端

    用例如下 移动应用程序正在通过 Google 对用户进行身份验证 并且在某些时候 我们需要将用户的视频发布到他的 YouTube 帐户 出于实际原因 实际发布应该由后端完成 已经存储在那里的大文件 由于用户已经通过应用程序的身份验证 因此应
  • 如何使用recv()检测客户端是否仍然连接(并且没有挂起)?

    我写了一个多客户端服务器程序C on SuSE Linux 企业服务器 12 3 x86 64 我为每个客户端使用一个线程来接收数据 我的问题是 我使用一个终端来运行服务器 并使用其他几个终端来运行服务器telnet到我的服务器 作为客户端
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • ASP MVC:服务应该返回 IQueryable 的吗?

    你怎么认为 你的 DAO 应该返回一个 IQueryable 以便在你的控制器中使用它吗 不 您的控制器根本不应该处理任何复杂的逻辑 保持苗条身材 模型 而不是 DAO 应该将控制器返回给视图所需的所有内容 我认为在控制器类中看到查询 甚至
  • 即使手动设置显示环境变量后,WSL Ubuntu 也会显示“错误:无法打开显示”

    我在 WSL Ubuntu 上使用 g 我使用 git 克隆了 GLFW 存储库 使用了ccmake命令配置并生成二进制文件 然后使用make在 build 目录中最终创建 a文件 我安装了所有OpenGL相关的库 usr ld 我不记得我
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin
  • 通过 NHibernate 进行查询,无需 N+1 - 包含示例

    我有一个 N 1 问题 我不知道如何解决它 可以在这个问题的底部找到完全可重复的样本 因此 如果您愿意 请创建数据库 设置 NUnit 测试和所有附带的类 并尝试在本地消除 N 1 这是我遇到的真实问题的匿名版本 众所周知 这段代码对于帮助
  • 在 C 中使用 GNU automake 中的解析器

    我是 GNU autotools 的新手 在我的项目中使用了 lex 和 yacc 解析器 将它们作为 makefile am 中的源代码会产生以下错误 配置 in AC CHECK PROGS YACC bison yacc none i
  • 当前的 x86 架构是否支持非临时加载(来自“正常”内存)?

    我知道有关此主题的多个问题 但是 我没有看到任何明确的答案或任何基准测量 因此 我创建了一个处理两个整数数组的简单程序 第一个数组a非常大 64 MB 第二个数组b很小 无法放入 L1 缓存 程序迭代a并将其元素添加到相应的元素中b在模块化
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解
  • 什么是 __declspec 以及何时需要使用它?

    我见过这样的例子 declspec在我正在阅读的代码中 它是什么 我什么时候需要使用这个构造 这是 Microsoft 对 C 语言的特定扩展 它允许您使用存储类信息来赋予类型或函数属性 文档 declspec C https learn
  • 转到定义:“无法导航到插入符号下的符号。”

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我今天突然开始在我的项目中遇到一个问题 单击 转到定义 会出现一个奇怪的错误 无法导航到
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我

随机推荐

  • c#输出当前日期和当前时间_如何在C#中的当前日期时间添加小时数?

    我们在C 中使用DateTime类的AddHours 方法 Syntax 句法 DateTime DateTime AddHours double 以下C 代码在当前日期时间添加小时数 using System namespace Cons
  • 父类和子类

    尽管很多知名译本都把C 面向对象里有继承关系的类称作基类和派生类 但人们很多口语化的表达里还是叫他们父类和子类 毕竟 你继承了我嘛 非亲非故的 谁让你继承 恰逢今天父亲节 我们就来聊聊C 里对父亲和儿子这一关系的设计 读程序 品人生 什么东
  • 优雅/粗暴地关闭TCP连接--close-shutdown的选择

    一个 TCP 连接需要经过三次握手进入数据传输阶段 最后来到连接关闭阶段 在最后的连接关闭阶段 我们需要重点关注的是 半连接 状态 因为 TCP 是双向的 这里说的方向 指的是数据流的写入 读出的方向 比如客户端到服务器端的方向 指的是客户
  • Lua封装延时执行函数

    延时执行函数 function delayTimeGuideEvent target func times 延迟时间执行函数 local delaytime 1 if times then delaytime times end getRo
  • Spring入门学习—Spring IOC

    一 什么是Spring Spring是一个轻量级的IOC DI和AOP容器的开源框架 目标 使现有技术更加易用 推进编码最佳实践 内容 IOC容器 AOP实现 数据访问支持 简化JDBC ORM框架 声明式事务 Web集成 设计理念 面向B
  • 平凡的世界

    1975年的二三月间 一个平平常常的日子 细蒙蒙的雨丝夹着一星半点的雪花 正纷纷淋淋地向大地飘洒着 时令已快到惊蛰 雪当然再不会存留 往往还没等落地 就已经消失得无影无踪了 黄土高原严寒而漫长的冬天 看来就要过去 但那真正温暖的春天 还远远
  • gitcode代码仓库的基本使用

    gitcode代码仓库的基本使用 一 gitcode官网简介 二 本地配置 1 安装git工具 2 配置本地git信息 3 查看git个人信息 二 创建本地仓库 1 创建本地工作区 2 将文件放入暂存区 3 将暂存区文件放入本地仓库 4 查
  • AutoML-第一章 超参数优化

    第一章 超参数优化 摘要 最近对具有许多超参数的复杂且计算成本很高的机器学习模型 例如自动化机器学习 AutoML 框架和深度神经网络 的兴趣引起了对超参数优化 HPO 的重新研究 在本章中 我们概述了 HPO 最主要的方法 我们首先讨论基
  • LinkedList 对比 ArrayList 的区别

    LinkedList 底层是双向链表 基于双向链表 无需连续内存 随机访问慢 要沿着链表遍历 头尾插入删除性能高 占用内存多 ArrayList 底层是数组 5 基于数组 需要连续内存 6 随机访问快 指根据下标访问 7 尾部插入 删除性能
  • 为什么32位的计算机内存最多4G

    1 计算机的最小存储单元 bit 位 一个bit用于存放一个二进制数 内存的单位 Byte 一个Byte 8bit 2 计算机会给每一个单位的内存 1Byte 分配一个地址 CPU是通过内存地址来调用内存中的数据的 调用方式是直接寻址 直接
  • ResNet50 结构

    ResNet有2个基本的block 一个是Identity Block 输入和输出的dimension是一样的 所以可以串联多个 另外一个基本block是Conv Block 输入和输出的dimension是不一样的 所以不能连续串联 它的
  • centos7 无法启动网络(systemctl start network.service )错误解决办法

    大家安装Centos7 系统后 可能会出现 网卡无法自动启动 需要在图形界面点击有线链接 才能正常上网 在这里就简单说下NetworkManager service 和network service的区别 前者是图像化管理网络连接的网络服务
  • SpringBoot定时任务设置

    1 主启动类加上注解 开启定时任务 EnableScheduling 2 创建定时任务类 import org springframework beans factory annotation Autowired import org sp
  • GAN的编写 - tensorflow形式(tensorflow与GAN同学习,重点分析训练过程)

    20200901 本文完成于20200902下午 前面内容还算整洁 越到后面因为都是自己思考的过程 就导致文章越来越乱 就算是把自己思考的过程给记录下来吧 0 引言 之前的时候对keras框架编写的GAN网络进行了介绍 GAN的学习 训练过
  • 基于控制的角度无人机集群——目标追踪

    无人机集群 目标追踪 前言 一 轨迹预测 二 单目标追踪 三 多目标追踪 前言 关于目标追踪问题 有一些研究是从视觉的角度展开 而我研究的是基于控制的角度 关于多无人机集群的一些知识点 已经在上一篇文章有了简单介绍 这次我想着重介绍一下 目
  • 4.抽样分布的概念与Python实现抽样

    1 总体与样本 在实际中 总体的分布一般是未知的 或只知道它具有某种形式而其中包含着未知参数 这时 常用的办法就是根据样本来推断总体 总体 个体 样本 总体 通常把研究对象的全体称为总体 一个总体对应于一个随机变量X 个体 把组成总体的每个
  • CTFshow 信息收集 web 6 7 8 9 10

    目录 第六关 提示 flag 第七关 提示 知识点 flag 第八关 提示 知识点 flag 第九关 提示 知识点 flag 第十关 提示 flag 第六关 提示 解压源码到当前目录 测试正常 收工 这道题考的是备份文件www zip 根据
  • 解决mysql占用IO过高

    created 2023 01 30T10 14 00 UTC 08 00 tags source https www bbsmax com A Ae5RyA0AJQ author 解决mysql占用IO过高 Excerpt 1 日志产生的
  • 西门子HMI设备与V20变频器如何实现通讯?

    通常情况下 要实现HMI设备与V20变频器的通讯 需要一个支持USS通讯或MODBUS通讯的PLC 比如S7 200系列PLC 其通讯电缆连接如图1所示 PLC的一个通讯端口与触摸屏连接 可以采用PPI协议通讯 PLC的另一个通讯端口与V2
  • C语言自定义类型-结构体

    一 结构体声明 C语言中为我们准备了许多现成的数据类型例如 int short float double char long long long 等等 但是我们描述一些复杂的事物 光靠上述的数据类型是描述不清的 例如 我们描述一个大学生 可