96SEO 2026-02-19 16:56 5
首先为什么要求这些自定义类型呢在C语言中其标准已经为我们提供了许多的内置类型int、char、double等等但是有些情况下人们发现单单靠这些内置类型无法满足现实世界各种复杂的情况例如如果我们要描述一本书我们是不是应该描述它的书名、作者、出版社等等各种信息我们发现如果此时只有内置类型是不可能达成类似这种复杂需求的于是C赋予了程序员们一种权利可以定义自定义类型。

而结构体就是自定义类型中的一种。
上面的类型就是一个匿名结构体类型有人看到这两个匿名结构体的成员变量完全一样那能不能这样做呢
首先这样做是不好的。
编译器对于匿名结构体的处理是如果匿名结构体的成员变量一样编译器也认为它们是不同的类型。
结构体的自引用简单理解就是结构体类型中的成员变量包含一个结构体类型的指针变量。
Node的成员next而这个成员也是一个自定义类型struct
Node类型的成员啊这种无穷包含自己在编译器看来是一种非法行为因为此时这个类型的大小无法确定。
而我们直到typedef可以对一种数据类型进行重命名那么它可以对结构体类型重命名吗当然可以。
例如如下
首先说答案上面这种声明是非法的因为此时的这个成员变量next的类型还没有完成重命名也就是先有鸡还是先有蛋的问题只有走完这个类型重命名语句才会对struct
Node不可以在重命名之前就使用重命名后的类型。
因此正确的命名是如下这种形式
有人一看这两个类型诶这两个类型的成员变量除了顺序不一样其他都是一样的啊让我算的话它们的大小难道不应该是
出人意料诶怎么回事不是6就是算了怎么这两个类型的大小还不一样。
为了解决这个问题我们要引出一个东西称之为结构体内存对齐规则。
如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。
有了结构体内存对齐规则我们就可以分析上面这两个结构体类型的大小为何如此了分析如下
声明为了更好理解下面的图由于结构体对齐规则导致没有使用的空间用红色表示
为了验证上面结构体成员的偏移量是否与预期正确我们可以用offsetof它是一个宏可以帮助我们计算一个结构体中某个成员变量相对于起始位置的偏移量。
不是所有的硬件平台都能访问任意地址上的任意数据的某些硬件平台只能在某些地址处取某些特定类型的数据否则抛出硬件异常。
原因在于为了访问未对齐的内存处理器需要作两次内存访问而对齐的内存访问仅需要一次访问。
那在设计结构体的时候如果我们既要满足对齐又要节省空间该如何做呢
type2的成员变量是一样的但是它们的大小确是不一样的前者占12个字节后者占8个字节原因就在于struct
我们知道VS下的默认对齐数是8但是我们却可以显式的修改其默认对齐数。
不推荐,值传递传参的压栈系统开销过大print2(information);
对于结构体的传参我们推荐采用以传结构体地址的方式因为函数在传参的时候会将其参数压栈在时间上和空间上都会有消耗如果我们传递一个结构体对象当这个结构体很大的时候参数压栈的系统开销就会很大会导致性能的降低而如果传递一个结构体指针其大小是固定的(32位下4个字节、64位下8个字节)可以节省系统的开销一定程度上提高性能。
上面就是一个位段我们可以看到位段的成员后面有一个冒号和一个数字这个数字代表着你这个成员占用了几个bit位例如a这个成员就会占用2个bit位。
那么位段的大小如何计算呢位段需要进行内存对齐吗
首先对于位段我们应该知道其主要作用是节省空间而我们知道结构体的内存对齐是以空间换取时间的一种方式很显然这就与位段的初衷相矛盾了故位段是不会有内存对齐的。
可以看到这个位段共占用了8个字节的确节省了空间。
那么位段究竟是如何分配内存的呢
位段涉及很多不确定因素位段是不跨平台的注重可移植的程序应该避免使用位段
之所以说位段是不跨平台的是由于当出现上面这种情况时我们不知道它的内存分配是怎样的例如上面剩余了15个bit位d到底有没有使用它是不确定的标准并没有明确规定是否使用这个15个bit。
因此对于位段的使用要小心如果要求程序具有移植性那么尽量减少位段的使用。
位段中最大位的数目不能确定。
16位机器最大1632位机器最大32写成27在16位机器会出问题。
位段中的成员在内存中从左向右分配还是从右向左分配标准尚未定义(vs下是从右向左分配的)。
当一个结构包含两个位段第二个位段成员比较大无法容纳于第一个位段剩余的位时是舍弃剩余的位还是利用这是不确定的(vs下没有利用剩余的空间)
位段较结构体相比位段可以达到同样的效果但是可以很好的节省空间但由于标准对许多细节并没有明确规定存在跨平台的问题其可移植性是有待商榷。
枚举enum是一种用于定义一组相关常量的数据类型。
它可以帮助开发人员更清晰地表示某个值的取值范围并提供更好的可读性和可维护性。
在枚举类型中我们可以定义一组具体的命名常量也称为枚举成员。
每个枚举成员都有一个与之关联的值它可以是数字如整数或者是其他数据类型如字符串。
枚举成员之间用逗号隔开。
使用枚举我们可以通过给定的枚举成员来表示某个特定的取值。
这有助于编写更可读的代码并减少硬编码所带来的错误。
此外枚举还可以作为函数参数、变量和属性的类型增加代码的类型安全性。
就是一种枚举类型{}中的内容是枚举类型的可能取值也称之为枚举常量这些枚举常量都是有值的默认从0开始依次递增1当然在定义的时候也可以赋初值例如
为什么要使用枚举常量呢它与#define定义的符号常量有什么区别呢
枚举常量是属于一种枚举类型的它是具有类型检查的与符号常量相比更为严谨
它可用于在同一内存空间中存储不同的数据类型。
它允许使用同一块内存来存储多种类型的数据但同一时间只能使用其中的一种类型数据。
联合与结构体非常相似都可以定义多个成员但联合只分配给它成员中最大的元素所需要的内存空间(需要考虑内存对齐,当最大成员的大小不是最大对齐数的整数倍时就需要内存对齐)。
因此联合可以通过不同的成员来表示同一块内存中的数据这使得它在一定程度上可以节省内存空间。
联合体的特征就是联合的成员共用同一块空间所以联合也叫共用体示例如下
联合的大小是由其最大的成员决定的例如上面的这个联合其最大成员是一个int类型又因为此时这个联合体的最大对齐数就是4因此上面这个联合的大小就是4。
可以发现联合对象和它的成员的地址是一样的也就是说其内存分配如图所示
联合的特定是成员共享同一块空间但这也限制了在同一时刻只可以使用一种成员。
例如
在使用联合时改变其中一个成员变量另一个成员变量也会被修改因此一般情况下联合在某一时刻下是单独使用一个成员变量的
ByteLSB存储在最高地址处。
也就是说数据的高位字节存储在低位地址低位字节存储在高位地址。
Endian则相反它是指将最低有效字节LSB存储在最低地址处最高有效字节MSB存储在最高地址处。
也就是说数据的低位字节存储在低位地址高位字节存储在高位地址。
利用联合的特性(其成员共有同一块空间)我们就可以判断某个机器下是大段还是小端存储那么如何判断呢
上面的联合体是多大呢注意联合体的的大小首先是要保证能够存放最大成员其次如果最大成员所占空间大小不是其最大对齐数的整数倍那么需要内存对齐。
例如上面的
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback