[学习资料] memset的使用

[复制链接]
 楼主| 小明的同学 发表于 2025-6-20 19:46 | 显示全部楼层 |阅读模式
为何要下面这样操作     
    uint8_t zero_buf[16];
    memset(zero_buf, 0, sizeof(zero_buf));难道声明一个新的数组后不是自动填充0吗?

在 C 语言中,局部数组声明后不会自动初始化为零,这是 C 语言的一个重要特性,也是内存管理的基础概念。
为什么需要显式初始化?
1. C 语言的内存管理原则
在 C 语言中:

局部变量(包括数组)存储在栈上

栈内存不会被自动初始化 - 它包含的是该内存位置上次使用后的残留值

全局变量和静态变量会被初始化为零,但局部变量不会

2. 未初始化数组的风险
如果省略 memset:
  1. uint8_t zero_buf[16]; // 包含随机垃圾值
当将这个数组发送给 OLED 时:

每个字节都是不可预测的值(可能是 0x00 到 0xFF 之间的任意值)

OLED 会将非零值解释为"亮"的像素点

结果:屏幕上会出现随机噪点而不是清晰的空白

 楼主| 小明的同学 发表于 2025-6-20 19:47 | 显示全部楼层
3. 性能与内存的权衡
使用 16 字节缓冲区是精心设计的平衡方案:
  1. // 方案对比
  2. uint8_t zero_buf[16];       // 栈空间: 16字节 → 安全
  3. memset(zero_buf, 0, 16);    // 快速初始化

  4. // 替代方案1: 128字节数组 → 栈溢出风险
  5. uint8_t big_buf[128] = {0}; // 可能超出小型MCU的栈空间

  6. // 替代方案2: 单字节写入 → 效率极低
  7. for(int i=0; i<128; i++) {  // 128次I2C传输 × 8页 = 1024次!
  8.     uint8_t zero = 0;
  9.     ssd1306_data(&zero, 1);
  10. }
优化建议


1. 静态常量优化 (推荐)
  1. void ssd1306_clear() {
  2.     // 静态常量 - 编译时初始化,不占额外RAM
  3.     static const uint8_t ZERO_BLOCK[16] = {0};
  4.    
  5.     for(uint8_t page = 0; page < 8; page++) {
  6.         // ...设置页地址...
  7.         for(uint8_t col = 0; col < 8; col++) {
  8.             // 使用常量数据块
  9.             ssd1306_data((uint8_t*)ZERO_BLOCK, sizeof(ZERO_BLOCK));
  10.         }
  11.     }
  12. }
优点:

零运行时初始化开销

不占用栈空间

可读性好

2. 汇编级优化 (极致性能)
  1. // 使用寄存器直接清零
  2. void ssd1306_fill_zero(uint8_t page) {
  3.     ssd1306_cmd(0xB0 | page);
  4.     ssd1306_cmd(0x00);
  5.     ssd1306_cmd(0x10);
  6.    
  7.     uint8_t buf[17] = {0x40}; // 0x40 = 数据头
  8.     // 编译器可能优化为块清零操作
  9.     for(int i=1; i<17; i++) buf[i] = 0;
  10.    
  11.     for(uint8_t i=0; i<8; i++) {
  12.         i2c_write(SSD1306_I2C_ADDR, buf, sizeof(buf));
  13.     }
  14. }



 楼主| 小明的同学 发表于 2025-6-20 19:48 | 显示全部楼层
C 语言局部变量不会自动初始化 - 这是有意为之的设计选择

显式初始化是良好实践 - 确保可预测的行为

小缓冲区设计是优化平衡:

内存效率 (16字节 vs 128字节)

I²C传输效率 (64次 vs 1024次)

静态常量是最佳实践 - 结合了安全性和性能

在嵌入式开发中,这种显式初始化模式很常见,它确保:

确定性行为(四轴飞行器像素)

可移植性(不依赖编译器实现)

资源高效利用(小内存占用)

理解这些底层细节有助于编写更可靠、高效的嵌入式代码!
 楼主| 小明的同学 发表于 2025-6-20 19:50 | 显示全部楼层
我也是今天才关注到这个问题的,然后收集资料,整理了这个帖子,希望对大家有帮助。之前我以为新建一个数组后就自动填充0了呢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

158

主题

1637

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

158

主题

1637

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部