2的幂次内存对齐:C代码中对齐字节计算逻辑解析
解析内存对齐字节计算公式的工作原理
先看代码里的核心公式:
adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1)); // calc alignment bytes
其中pSZ是sizeof(char*)(指针大小,32位系统为4,64位为8,必然是2的幂,这是位运算生效的前提),tot是源字符串的总长度(包含终止符\0)。
公式拆解步骤
tot + pSZ-1:凑出跨越对齐边界的数值
把原始数据大小加上对齐粒度减1,目的是让原本未对齐的tot,变成一个超过下一个pSZ倍数边界的数。比如pSZ=8、tot=10时,10+7=17,已经超过了下一个8的倍数16;如果tot本身是8的倍数(比如8),8+7=15,刚好是下一个倍数(16)的前一个数。(tot + pSZ-1) & (pSZ-1):取余数
因为pSZ是2的幂,pSZ-1的二进制是低位全1的掩码(比如8-1=7是0b111)。按位与操作会保留tot + pSZ-1的低log2(pSZ)位,这等价于计算(tot + pSZ-1) % pSZ,也就是这个数除以pSZ的余数。- 例子:
tot=10时,17&7=1(余数1);tot=8时,15&7=7(余数7);tot=7时,14&7=6(余数6)。
- 例子:
(pSZ-1) - 余数:计算需要补充的对齐字节
用对齐粒度减1的值减去余数,得到的就是需要额外添加的字节数,让tot + adj刚好是pSZ的倍数:tot=10:7-1=6,10+6=16(8的倍数)tot=8:7-7=0,无需补充(已经对齐)tot=7:7-6=1,7+1=8(对齐)
设计意图
这段代码要分配的内存不仅要存储原始字符串,还要在后续空间存放指针数组(函数返回char**类型)。指针的访问要求对齐到指针大小的边界,所以先把字符串的存储空间对齐到pSZ的倍数,后面的指针数组就能自然满足对齐要求,避免因未对齐导致的性能损耗或架构层面的访问错误。
内容的提问来源于stack exchange,提问作者dandan13
相关产品推荐
相关产品推荐

