揭秘C语言联合体与位域对齐:99%程序员忽略的内存对齐陷阱

第一章:C语言联合体与位域对齐的神秘面纱

在C语言中,联合体(union)和位域(bit-field)是两个强大但常被误解的特性。它们允许开发者以更精细的方式控制内存布局,尤其适用于嵌入式系统、协议解析等对空间敏感的场景。然而,由于内存对齐和数据覆盖机制的存在,使用不当极易引发未定义行为或跨平台兼容性问题。

联合体的内存共享机制

联合体中的所有成员共享同一块内存空间,其大小由最大成员决定。这意味着写入一个成员会覆盖其他成员的数据。

union Data {
    int i;        // 4字节
    float f;      // 4字节
    char str[8];  // 8字节
};
// sizeof(union Data) = 8
当向 i 写入后,再读取 f 将得到该整数位模式对应的浮点解释,这在类型双关(type punning)中常见,但需注意严格别名规则。

位域与内存对齐策略

位域允许将结构体成员压缩到指定的比特位数,常用于节省存储空间。

struct Flags {
    unsigned int is_valid : 1;
    unsigned int priority : 3;
    unsigned int status   : 2;
} __attribute__((packed));
上述结构体理论上仅需6位,但由于编译器默认对齐策略,实际可能占用4字节。使用 __attribute__((packed)) 可禁用填充,确保紧凑布局。

对齐行为的平台依赖性

不同架构和编译器对联合体与位域的处理存在差异。以下表格展示了常见数据类型的对齐要求:
数据类型典型大小(字节)对齐边界(字节)
char11
int44
short22
合理使用 #pragma pack 或属性指令可控制对齐方式,避免因隐式填充导致结构体膨胀。

第二章:联合体与位域的底层原理剖析

2.1 联合体内存布局与成员共享机制

联合体(union)在C/C++中是一种特殊的数据结构,其所有成员共享同一段内存空间。联合体的总大小等于其最大成员的大小,内存布局由对齐规则决定。
内存布局示例

union Data {
    int i;      // 4字节
    float f;    // 4字节
    char str[8]; // 8字节
};
上述联合体大小为8字节,所有成员从同一地址开始。写入一个成员后读取另一个将导致未定义行为,因数据解释方式不同。
成员共享与数据重解释
联合体常用于类型双关(type punning),例如将浮点数拆解为整型位模式:

union FloatInt {
    float f;
    uint32_t i;
};
union FloatInt u;
u.f = 3.14f;
printf("Bits: 0x%x\n", u.i); // 直接访问位表示
此技术依赖于共享内存机制,但需注意平台字节序和严格别名规则限制。
  • 所有成员起始地址相同
  • 任意时刻仅一个成员有效
  • 可用于节省内存或底层数据转换

2.2 位域的定义语法与存储压缩特性

位域是C/C++中用于优化内存布局的重要机制,允许将多个布尔标志或小范围整数紧凑地存储在一个字节或字内。
位域的基本语法

struct Flags {
    unsigned int is_ready : 1;
    unsigned int state   : 3;
    unsigned int mode    : 4;
};
上述结构体定义了三个位域成员:`is_ready`占用1位,`state`占用3位,`mode`占用4位。编译器会将其打包进一个至少8位宽的存储单元中,显著减少内存开销。
存储压缩原理
位域通过按位分配实现空间压缩。例如,在32位系统中,若不使用位域,每个int默认占4字节;而位域可将多个字段压缩至单个unsigned int中。连续声明的位域按内存顺序从低位向高位填充(具体依赖编译器和架构)。
  • 位域宽度必须是非负整数且不超过基础类型的位宽
  • 未命名位域可用于填充对齐,如:4
  • 跨平台移植时需注意字节序和位域布局差异

2.3 数据对齐与填充字节的生成规则

在结构体内存布局中,数据对齐机制确保成员按特定边界访问,以提升CPU读取效率。编译器依据目标平台的对齐要求,在成员间插入填充字节。
对齐规则示例
struct Example {
    char a;     // 1字节
    int b;      // 4字节
    short c;    // 2字节
};
该结构体中,`char a` 后需填充3字节,使 `int b` 对齐到4字节边界;`short c` 占2字节,总大小为12字节(含末尾填充)。
常见类型的对齐值
类型大小(字节)对齐边界
char11
short22
int44
double88
填充字节的生成由编译器自动完成,遵循“成员对齐、整体对齐”原则。结构体总大小必须是其最大成员对齐值的整数倍。

2.4 联合体中位域的共存与冲突分析

在C语言联合体(union)中,多个成员共享同一段内存,当成员包含位域时,其布局受编译器和字节序影响,易引发共存与冲突问题。
位域内存布局示例

union Data {
    struct {
        unsigned int a : 4;
        unsigned int b : 4;
    } part;
    unsigned char raw;
};
该联合体中,part 的两个4位字段与 raw 共享1字节。若向 a 写入5,b 写入9,则 raw 的值为 (9 << 4) | 5 = 149,体现位域紧凑存储特性。
潜在冲突场景
  • 不同架构下位域分配顺序(高位优先或低位优先)不一致
  • 跨平台数据解析时,联合体解码结果可能错乱
  • 未对齐访问可能导致性能下降或硬件异常

2.5 编译器差异对对齐行为的影响

不同编译器在处理数据结构对齐时可能采用不同的默认策略,这直接影响内存布局和跨平台兼容性。例如,GCC、Clang 和 MSVC 对 #pragma pack 的解析和默认对齐边界存在差异。
常见编译器对齐行为对比
编译器默认对齐支持指令
GCC按类型自然对齐#pragma pack, __attribute__((aligned))
MSVC同左,但#pragma pack 默认值不同#pragma pack, __declspec(align)
Clang与 GCC 兼容支持 GCC 扩展
代码示例:结构体对齐差异

struct Example {
    char a;     // 偏移 0
    int b;      // GCC/Clang: 偏移 4;MSVC 可能不同
};
上述结构体在不同编译器下可能产生不同大小(8 或 12 字节),因对齐填充策略不一致。使用 #pragma pack(1) 可强制紧凑布局,但可能降低访问性能。跨平台开发需显式控制对齐以确保二进制兼容性。

第三章:内存对齐陷阱的典型场景再现

3.1 结构体内嵌联合体位域的错位问题

在C语言中,结构体内嵌联合体并结合位域使用时,容易因内存对齐和字段布局不一致导致数据错位。编译器对位域的分配策略依赖于目标平台的字节序和对齐规则,可能引发不可预期的内存覆盖。
典型错误示例

struct Packet {
    unsigned int type : 4;
    union {
        unsigned int data : 12;
        struct { int flag; } ext;
    } payload;
};
上述代码中,payload内的data为12位位域,但其与ext共享同一内存空间。若访问ext.flag,将无视位域边界,直接读写整个int宽度,造成越界访问。
内存布局风险分析
  • 位域跨字节存储时,不同编译器处理顺序不同(大端/小端)
  • 联合体内非位域成员会强制对齐到自然边界,破坏紧凑布局
  • 结构体总大小可能因填充而扩展,影响跨平台兼容性

3.2 跨平台移植中的对齐不一致案例

在跨平台移植过程中,数据结构的内存对齐差异常引发严重问题。不同架构(如x86与ARM)对边界对齐的要求不同,可能导致结构体大小不一致或字段错位。
典型结构体对齐差异

struct Packet {
    uint8_t  flag;    // 1 byte
    uint32_t value;   // 4 bytes
};
在32位系统中,该结构体因内存对齐可能占用8字节(flag后填充3字节),而在某些嵌入式平台上可能仅使用5字节,导致跨平台数据解析错误。
规避策略
  • 使用编译器指令(如#pragma pack)统一对齐方式
  • 序列化时采用标准格式(如Protocol Buffers)
  • 避免直接内存拷贝,通过访问器函数读写字段

3.3 位域跨字节边界的读写异常演示

在C语言中,位域允许将多个布尔或小整型字段打包到同一个整型变量中以节省空间。然而,当位域跨越字节边界时,不同编译器对内存布局的处理方式可能导致不可预测的行为。
位域定义示例

struct Packet {
    unsigned int flag1 : 5;
    unsigned int flag2 : 4; // 跨越字节边界
};
该结构中,flag1占用5位,紧随其后的flag2需要4位,但两者位于不同的字节边界上。某些编译器会填充剩余3位并重新开始下一字节,而其他编译器可能尝试紧凑排列,导致跨平台兼容性问题。
潜在风险分析
  • 不同架构下内存对齐策略差异引发数据截断
  • 位域成员访问出现意外的值溢出或覆盖
  • 结构体大小因编译器优化而变化
建议避免跨字节边界使用连续位域,或通过静态断言确保跨平台一致性。

第四章:规避策略与高效编程实践

4.1 使用#pragma pack控制对齐方式

在C/C++中,结构体成员默认按其类型自然对齐,可能导致内存浪费。`#pragma pack` 指令允许开发者显式控制结构体的内存对齐方式,优化空间使用。
基本语法与用法

#pragma pack(push, 1)
struct PackedData {
    char a;     // 偏移 0
    int b;      // 偏移 1(非对齐)
    short c;    // 偏移 5
}; 
#pragma pack(pop)
上述代码将结构体成员以字节为单位紧凑排列,push保存当前对齐状态,1表示按1字节对齐,pop恢复之前的设置。
对齐方式对比
成员默认对齐偏移#pragma pack(1) 偏移
char a00
int b41
short c85
使用 `#pragma pack(1)` 可减少填充字节,适用于网络协议或嵌入式系统中的内存敏感场景。

4.2 静态断言验证结构体大小与偏移

在系统级编程中,确保结构体的内存布局符合预期至关重要。静态断言(static assertion)可在编译期验证结构体大小和成员偏移,避免因编译器填充或对齐策略导致的运行时错误。
使用静态断言检查结构体大小

#include <assert.h>
#include <stddef.h>

typedef struct {
    char flag;
    int value;
    short data;
} Packet;

_Static_assert(sizeof(Packet) == 16, "Packet size must be 16 bytes");
该代码确保 Packet 结构体总大小为 16 字节。若实际大小不符,编译将失败,并提示指定消息。
验证成员偏移一致性
  • _Static_assert(offsetof(Packet, value) == 4):确认 value 成员位于第 4 字节;
  • 防止跨平台移植时因对齐差异引发数据解析错误;
  • 常用于协议封装、内存映射I/O等对布局敏感的场景。

4.3 手动填充与字段排序优化技巧

在高性能数据结构设计中,手动填充(Manual Padding)常用于避免伪共享(False Sharing),特别是在多核并发场景下。通过在结构体中插入占位字段,可确保不同CPU核心访问的变量位于独立的缓存行中。
手动填充示例
type PaddedCounter struct {
    count1 int64
    _      [8]int64 // 填充至64字节,避免与count2共享缓存行
    count2 int64
}
该代码通过添加一个长度为8的int64数组(共512位),使count1和count2位于不同的缓存行,消除伪共享带来的性能损耗。
字段排序优化策略
合理排列结构体字段可减少内存对齐带来的空间浪费。应将大尺寸字段前置,相同类型连续排列:
  • 优先放置int64、float64等8字节类型
  • 紧随其后是4字节(如int32)、2字节类型
  • 最后放置bool、int8等小尺寸字段

4.4 利用offsetof宏进行运行时安全检查

在C语言系统编程中,offsetof 宏是 <stddef.h> 提供的关键工具,用于获取结构体成员相对于结构体起始地址的字节偏移。这一特性可被巧妙用于运行时的安全性验证。
offsetof的基本用法
#include <stddef.h>
#include <stdio.h>

typedef struct {
    int id;
    char name[32];
    double score;
} Student;

// 获取score成员的偏移
size_t offset = offsetof(Student, score);
printf("score offset: %zu\n", offset); // 输出:40(取决于对齐)
该代码演示了如何计算 score 字段在 Student 结构中的偏移位置,常用于序列化或内存拷贝场景。
运行时类型安全检查
通过预计算关键字段偏移,并在程序启动时校验,可防止因结构体布局变更引发的兼容性问题:
  • 确保跨编译器或配置下的内存布局一致性
  • 检测误用的结构体填充或对齐设置
  • 增强内核模块或共享内存通信的健壮性

第五章:结语——掌握底层,远离隐患

深入理解系统调用的必要性
在高并发服务开发中,频繁的系统调用可能成为性能瓶颈。以 Linux 的 epoll 为例,若未正确使用边缘触发(ET)模式,可能导致事件遗漏:

// 正确的 ET 模式处理:必须循环读取直到 EAGAIN
while ((n = read(fd, buf, sizeof(buf))) > 0) {
    // 处理数据
}
if (n == -1 && errno != EAGAIN) {
    // 处理错误
}
内存管理中的常见陷阱
Go 开发者常忽视逃逸分析对性能的影响。通过 go build -gcflags="-m" 可查看变量逃逸情况。以下结构极易导致内存泄漏:
  • 全局 map 未设置过期机制
  • goroutine 持有大对象引用且未正确关闭
  • http.Client 未配置超时或连接池
生产环境故障排查案例
某支付网关偶发延迟毛刺,经 perf record 分析发现大量 sys_exit_group 调用。最终定位为日志库在每条日志后调用 fsync(),改为批量刷盘后 P99 延迟下降 83%。
优化项优化前优化后
日志刷盘频率每次写入每 10ms 批量提交
P99 延迟217ms37ms

代码逻辑 → 系统调用分析 → 内存逃逸检测 → 性能火焰图 → 生产验证

用C语言联合体(union)和位域(bit-field)优雅管理Modbus通讯状态机 本文介绍了如何利用C语言的联合体(union)和位域(bit-field)技术高效管理Modbus通讯状态机。通过5个关键技巧,包括内存布局优化、多视图访问模式设计、中断安全的原子操作、协议版本兼容性扩展和调试增强,显著提升嵌入式系统的内存利用率和代码可维护性。特别适用于485总线等资源受限的工业控制场景。 阅读详情

相关推荐

VisionMaster位置修正功能深度解析:如何让找圆工具自动跟随移动目标?

本文深度解析海康威视VisionMaster平台的位置修正功能,重点介绍如何通过模板匹配与找圆工具的智能联动实现移动目标的动态追踪。文章详细阐述了工业视觉检测中的坐标系同步原理、模板匹配配置技巧及异常处理策略,为工程师提供了一套完整的工业级解决方案。

uu89012的博客 282

联合体(共用体) 和 位域 的使用详细解析

联合体(共用体) 和 位域 的使用详细解析

枕上青灯竹书香的博客 5672

利用featureCounts实现高效转录本定量:从比对到下游分析

本文详细介绍了利用featureCounts工具进行RNA-seq转录本定量的完整流程。从软件安装、输入文件准备,到核心命令参数解析与批量样本处理,再到将生成的计数矩阵无缝衔接至DESeq2进行差异表达分析,提供了从比对到下游分析的一站式实战指南。文章重点阐述了featureCounts在效率与易用性上的优势,并分享了常见问题排查与性能优化技巧,帮助研究者高效完成转录本定量这一关键步骤。

weixin_29069131的博客 319

联合体、位域

本文参考自:https://blog.youkuaiyun.com/whahu1989/article/details/84575558?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.vipsorttest&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7

miaocuilin的专栏 1534

从三个角度理解知识图谱

2012年谷歌首次提出“知识图谱”这个词,由此知识图谱在工业界也出现得越来越多,对于知识图谱以及相关概念的理解确实也是比较绕。自己在研究大数据独角兽Palantir之后开始接触知识图谱,也算对其有了一定了解,这里从三个角度总结一下怎么去理解知识图谱。 几个基本概念:本体、实体、知识库、知识图谱 1、本体是概念的集合,是大家都公认的概念框架,一般不会改变如“人”、“事”、“物”、 “地”、“组...

JavaChaoCo的博客 6902

Cursor自动生成测试用例

或者把你已有的规则直接复制粘贴到这个文档内(这里我用的是Markdown格式和CSV格式的测试用例生成规则,可以同时生成Markdown和CSV格式的测试用例)。在AI对话框这里,我们可以看到Cursor会逐步来帮我们生成测试用例,先分析识别需求文档,然后生成测试用例,最后会进行质量检查,确保生成的用例符合规范。生成的Markdown格式,可直接导入Xmind,生成思维导图,对应到具体的功能模块看具体的测试点,逻辑会更直观一些。(1)选中规则文档和需求文档:@你的测试用例规则文档@你的需求文档。

十二测试录 2433

联合体与位段(位域)

在C语言中,变量的定义是分配存储空间的过程。一般的,每个变量都具有其独有的存储空间,那么可不可以在同一个内存空间中存储不同的数据类型(不是同时存储)呢?答案是可以的,使用联合体就可以达到这样的目的。联合体也叫共用体,在C语言中定义联合体的关键字是union。

weixin_73530513的博客 1069

Java的API帮助文档

JDK帮助文档 SUN公司为JDK工具包提供了一整套文档资料,我们习惯上称之为JDK文档。 JDK文档中提供了Java中的各种技术的详细资料,以及JDK中提供的各种类的帮助说明。 JDk文档是Java语言的完整说明,大多数书籍中的类的介绍都要参照它来完成,它是编程者经常查阅的资料 如何理解API:就当做是一个“字典”,“使用手册”,API就相当于是一个电子的帮助文档,可以帮我们查看JDK提供的类的信息,平时查看的时候可结合百度一起看。 官网下载: 1、登录Oracle官网(Oracl.

人生得意须尽欢 2万+

联合体和位域的结合

总的来说,联合体和位域的结合使用可以在某些场景下提供更高效和灵活的内存管理方式。然而,需要注意跨平台兼容性、可读性和可维护性,以及位域的范围限制。位域成员变量的类型必须是整型(signed或unsigned)或枚举类型。位域是一种用于在一个字节或更小的空间中存储多个标志位或数据的机制。位域使用冒号 : 来声明成员变量所占用的位数。

qq_45780653的博客 1044

Python爬虫实战:利用Selenium与反反爬技术高效爬取企查查工商信息

本文将详细介绍如何使用Python最新爬虫技术(包括Selenium、Playwright、智能代理池等)爬取企查查工商信息数据。文章包含完整的代码实现、反反爬策略、数据解析与存储方案,以及法律合规性讨论,共计约8000字。企查查作为国内领先的企业信息查询平台,收录了超过2亿家企业的工商信息、司法信息、知识产权等数据。这些数据对于市场分析、商业决策等具有重要价值。法律边界提示禁止大规模爬取导致服务器过载不得绕过付费接口获取数据数据使用需遵守《个人信息保护法》商业用途需获得授权。

2201_76125261的博客 2237

第2.0章 机器人C++学习开篇(一):SLAM为什么使用C++语言及学习路线资料推荐

ROS(机器人操作系统):机器人领域的“操作系统”,提供节点通信、参数管理、工具链支持,是SLAM算法在机器人上部署的核心框架。PCL(点云库):处理三维点云数据的利器,包含滤波、分割、配准等算法,是激光SLAM的核心依赖。Eigen(矩阵运算库):高效的矩阵与线性代数运算库,SLAM中的位姿变换、优化求解都依赖它。Ceres/G2O(优化库):SLAM后端优化的“王牌”,Ceres擅长通用非线性优化,G2O则专为图优化设计,二者是BA( bundle adjustment)等算法的实现基础。

行知SLAM 1244

揭秘联合体与位域的内存对齐机制:99%的嵌入式开发者都忽略的关键细节

掌握C语言联合体的位域对齐技巧,解决嵌入式开发中内存布局难题。详解对齐机制、适用场景与优化方法,提升数据存储效率,避免跨平台兼容问题。深入剖析底层原理,值得收藏。

SimProceed的博客 375

Arduino I2C for TCA9548A应答扫描程序

Arduino I2C for TCA9548A应答扫描程序

perseverance51博客 1119

结构体 + 联合体 + 位域 使用

简单介绍结构体 定义结构体,一般是对有相同属性的元素或成员的归纳,比如电机的电气特性:驱动电压、驱动电流、运行速度;还有比如系统报警类:过压报警、过流报警、欠压报警 本人常用格式 typedef struct { u8 Volt;//成员变量 u8 Curr; u16 Speed; }Motor_InitTypeDef; 当然,还有其它的格式,可以自行查找 使用方法: Motor_InitTypeDef Motor_InitStre;//定义结构体变量 Motor_InitStr...

yuyan7045的博客 3291

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

联合体 位域结构体_【C语言笔记】位域

位域的概念有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种数据结构,叫做“位域”或“位段”。位域是操控位的一种方法(操控位的另一种方法是使用按位运算符,按位运算符将在之后的笔记中做介绍)。位域通过一个结构声明来建立:该结构声明为每个字段提供标签,...

weixin_39942108的博客 583

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

OC对象原理探究(下)—— 联合体(共用体)与位域

在开发中,有时候内存和存储空间极其有限的情况下(比如嵌入式等),常规的iOS对象存储方式,对内存的开销就不符合开发要求了,这时候,我们会采用其他的存储方式:联合体和位域。 一、认识联合体 1、什么是联合体 联合体也叫共用体,是一种特殊的类,也是一种构造类型的数据结构。 在一个联合体内能够定义多种不同的数据类型。一个被说明为该联合体类型的变量中。同意装入该联合体所定义的不论什么一种数据。这些数据共享同一段内存,以达到节省空间的目的。 2、联合体的两个特性 ① 在union中,分配内存空间的大小,等.

罗永涛的技术博客 1104

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【专家级技巧】:利用联合体位域对齐实现高效寄存器访问(附真实案例)

掌握C语言联合体的位域对齐技巧,高效实现寄存器访问与硬件控制。适用于嵌入式开发中内存优化与数据封装,通过联合体结合位域精确操作特定位段,提升运行效率与代码可读性。真实案例解析,值得收藏。

ByteVein的博客 416

位域与联合体

位域:是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字

MENGHUANBEIKE的专栏 2213

【C语言中联合体(共用体)详解】

在C语言中,联合体(union),又称为共用体,是一种特殊的数据结构。它与结构体类似,但所有成员共享同一块内存,因此可以在不同时间存储不同类型的数据。联合体在节省内存和处理多态数据时非常有用。在C语言中,使用unionunion 联合体名 {数据类型 成员1;数据类型 成员2;...✅int i;float f;");// 查看内存大小printf("sizeof(data) = %lu 字节\n", sizeof(data));return 0;✅。

武帝为此的博客 1837

C语言之结构体,位域,联合体

结构体 C语言中的一种自定义类型 需要程序员自己先把类型定义出来,再用该类型声明变量 定义结构 为了定义结构,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下: ​``` struct tag { member-list member-list member-list ... } vari...

qq_42667970的博客 1290

结构体+联合体+位域的实际使用

结构体、联合体

qq_45294059的博客 2839

联合体 位域结构体_C/C++中的位域

各种基本数据类型中,长度最小的 char 和 bool 在内存中占用一个字节的空间,但对于某些数据类型只需要几个二进制位即可保存,例如:enum GameResult { WIN, LOSE, TIE, CANCEL };由于它只有四种取值,只需要两个二进制位就可保存,而一个 GameResult 类型变量至少要占1个字节(8个二进制位),在很多编译器中,甚至还会占据更多的空间。单一变量所浪费的空...

weixin_39936134的博客 520

结构体或联合体中的位域

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域

K_Linux_ManのBlog 3808

c++节省内存 联合体和位域的使用

一:union 联合体 首先我们需要知道struct和union的区别:struct的大小遵循字节对齐。union的成员是共享内存的,其大小由最大的成员变量决定。 32位和64位的区别是 long的字节数和指针所占的字节数。 这里我们只讲位域和联合体的小端模式下内存的字节占用情况。 我们举个栗子: #include &lt;iostream&gt; #include &lt;cstdi...

DK 921

20150127 【 ARM 】 C语言+位域联合体

结构体位域 struct Fpga { unsigned int a:1; unsigned int b:1; unsigned int c:1; }; 联合体:多个成员共用一块存储空间(占最大数据类型空间) 同一时刻只能用一个成员 union FPH { unsigned int p; unsigned char ch; }; union FPH mfph; m

描绘自己的王国…… 1406
上一篇: 掌握三数取中法,3分钟解决C语言快排不稳定难题
下一篇: 二叉树镜像反转:5分钟彻底搞懂递归思维的本质
CompiLume
博客等级 码龄1年 168粉丝 2185原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值