c++ - memcpy 中的指针运算有奇怪的结果
问题描述
几年后我回到了 C 编程,所以我想我有点生疏了,但是我在我的代码中看到了一些奇怪的行为。
我有以下内容:
memcpy(dest + (start_position * sizeof(MyEnum)), source, source_size * sizeof(MyEnum));
在哪里:
dest
并且source
是MyEnum
不同大小的数组,dest
是 64 字节长。source
长度为 16 个字节。sizeof(MyEnum)
是4
字节source_size
是4
,因为数组中有 4 个枚举。
我循环这段代码 4 次,start_position
每次都前进,所以在 4 次循环迭代中的每一次,我都memcpy
被调用以下值(我已经用调试器检查了这个):
memcpy(dest + (0), source, 16);
(start_position
= 0 * 4,因为source
大小是 4)memcpy(dest + (16), source, 16);
(start_position
= 1 * 4,因为source
大小是 4)memcpy(dest + (32), source, 16);
(start_position
= 2 * 4,因为source
大小是 4)memcpy(dest + (48), source, 16);
(start_position
= 3 * 4,因为source
大小是 4)
memcpy
在第一个循环中工作正常,但在第二个循环中,它将数据复制到另一个数组,显然超出了dest
数组的内存区域,违反了另一个数组的内存区域。
所以我检查了函数内部发生的指针运算,这就是我得到的:
dest
地址是0xbeffffa74
dest + (start_position * sizeof(MyEnum))
是0xbefffab4
为了(start_position * sizeof(MyEnum)
=16
- 被违反的数组位于
0xbefffab4
。
虽然这解释了为什么数组的内存被侵犯,但我不明白0xbeffffa74 + 16
会发生什么0xbefffab4
,但我可以确认这memcpy
是被调用的地址。
我在 Raspberry Pi 上运行它,但 AFAIK 这应该没关系。
解决方案
指针算法适用于指向数据类型的大小。如果你有一个char*
然后你增加指针它会移动一个。如果它是一个,int*
那么每个增量都会增加一个以上,通常是 4 到指针(由于 int 通常,但不总是,是 32 位)。
如果您有一个指向结构的指针,那么递增指针会将其移动结构的大小。因此,sizeof
不应该在那里,否则你会移动太多。
memcpy(dest + (start_position * sizeof(MyEnum)), source, source_size * sizeof(MyEnum));
由于MyEnum
是四个字节,因此每个位置都会移动指针 4*4 字节。
memcpy(dest + start_position, source, source_size * sizeof(MyEnum));
这一次只移动 4 个字节。
这是合乎逻辑pointer[2]
的,因为*(pointer + 2)
如果指针算术没有隐式地考虑指向的类型大小,那么所有索引也需要,sizeof
并且你最终会写很多pointer[2 * sizeof(*pointer)]
.
推荐阅读
- excel - 如何复制带有空白单元格的列并粘贴到新的工作表 VBA 中?
- extjs - 如何在 ExtJs 中绑定监听器?
- reactjs - i18next 适用于开发服务器,但不适用于 azure app-service
- r - 根据R中上一行或下一行的值在列中添加缺失值
- javascript - 如何创建正则表达式以过滤掉关于长度、大小写和字符类别的复杂条件很少的结果
- atom-editor - 无法在 Atom 上安装 term3。(Ubuntu)
- css - 是否可以在具有混合混合模式的动画画布后面使用静态背景?
- security - Suricata HOME_NET 配置问题(SPAN 端口)
- javascript - 使用简单的 JavaScript 从 textarea 内容发送推文并发送到 WhatsApp
- playframework - 使用 sonarQube 扫描播放帧代码的最佳方法