memcpy是否识别目标内存底层大小?输出与预期不符问题咨询
为什么memcpy的结果和你预期不一样?
嘿,这个问题其实戳中了两个容易忽略的点:memcpy的本质和系统字节序的影响,咱们一步步理清楚:
1. memcpy才不管目标内存的「底层大小」呢
memcpy的工作逻辑特别直白——它就是个纯粹的「字节搬运工」:你告诉它要搬多少个字节(第三个参数),它就从源地址开始,把对应数量的字节原封不动逐字节搬到目标地址。它完全不会去分析目标变量是什么类型、占多少字节,更不会关心字节序这种底层细节。
举个例子,你的代码大概率是类似这样的:
uint8_t a = 0x01; uint64_t b = 0; memcpy(&b, &a, sizeof(a)); // 只复制1个字节
这里memcpy确实严格执行了你的要求:把a的1个字节(0x01)复制到了b的内存起始位置——但问题出在,这个起始位置对应的是uint64_t数值的哪一部分?
2. 字节序(Endianness)才是关键
你看到的结果0000000000000001,说明你的运行环境是小端字节序(Little Endian),这是目前绝大多数x86/x86_64架构系统的默认设置:
- 在小端系统里,多字节类型的**最低有效字节(LSB,也就是数值里最小的那部分)**会存在内存的最低地址处
- 拿uint64_t的
b来说,它的内存布局是:地址最靠前的位置存的是数值的第07位(最低字节),地址最靠后的位置存的是第5663位(最高字节)
所以当你把0x01复制到b的起始地址(最低地址),对应的就是uint64_t的最低字节,最终数值自然就是0000000000000001。
而你预期的0000000100000000,是**大端字节序(Big Endian)**下的表现:大端系统会把多字节类型的最高有效字节(MSB)放在内存最低地址处,这时候复制第一个字节才会对应数值的最高位部分。
想得到预期结果该怎么做?
如果不管系统字节序,都想让0x01成为uint64_t的第4个字节(对应0000000100000000),你可以:
- 手动计算内存偏移,把字节复制到目标位置:
memcpy(((uint8_t*)&b) + 4, &a, sizeof(a)); // 偏移4个字节,将0x01放到第4个字节位置 - 或者用更直观的位运算赋值:
b = (uint64_t)a << 32; // 把0x01左移32位,直接放到对应位置
内容的提问来源于stack exchange,提问作者Valentin
相关产品推荐
相关产品推荐

