使用单个memset清零类中多个数组是否合法?能否假定内存连续?
问题解答
1. 这种写法是否符合C++标准规范?
不合法,属于依赖特定平台实现的未定义行为。
C++标准仅保证:同一访问控制区段(这里几个数组都属于private区段)的非静态成员变量,会按照声明顺序从低到高排列内存地址,但不保证成员之间没有填充字节。填充字节是编译器为了满足变量对齐要求自动插入的,标准没有统一约束,不同平台、不同编译配置都可能有差异。
不过在Arduino项目的目标运行环境下,这段代码实际上可以正常运行:
- ARM平台下代码显式给每个数组加了
__attribute__((aligned(4))),每个数组长度刚好4字节,对齐要求一致,编译器不会在成员之间插入填充,5个数组刚好占据连续的20字节内存 - AVR平台下
uint8_t默认对齐要求为1,同类型连续数组成员也不会有填充,内存同样连续
2. 开发者为什么选择这种写法?
核心是简化代码,而非性能收益:
对总长度仅20字节的内存清零操作,单次memset和拆分5次每次清4字节的性能差异微乎其微,在绝大多数嵌入式场景下完全可以忽略。这种写法只需要一行代码就可以完成5个数组的清零,避免重复写5次memset,减少冗余代码的同时也降低了漏写某个成员的概率。
3. 这种写法的风险
这种写法非常脆弱,后续维护只要出现以下任意一种情况都会触发bug:
- 有人在这5个数组之间新增了其他成员变量
- 某个数组的长度、对齐属性被修改
- 项目新增支持了其他对对齐规则要求不同的平台
更规范的实现方式有两种: - 给每个数组单独调用
memset清零 - 把这5个地址连续的数组合并为一个结构体,或者合并为一个长度20的
uint8_t数组,再整体执行memset,这种方式符合C++标准,不存在兼容性风险
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

