memcpy 中的指针运算有奇怪的结果[重复]

Posted

技术标签:

【中文标题】memcpy 中的指针运算有奇怪的结果[重复]【英文标题】:Pointer arithmetic in memcpy has weird result [duplicate] 【发布时间】:2019-09-15 06:01:41 【问题描述】:

几年后我又回到了 C 编程领域,所以我想我有点生疏了,但我在我的代码中看到了一些奇怪的行为。

我有以下:

memcpy(dest + (start_position * sizeof(MyEnum)), source, source_size * sizeof(MyEnum));

地点:

destsourceMyEnum 大小不同的数组, dest 的长度为 64 个字节。 source 的长度为 16 个字节。 sizeof(MyEnum)4 字节 source_size4,因为数组中有 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 这应该没关系。

【问题讨论】:

【参考方案1】:

指针算法适用于指向数据类型的大小。如果你有一个char*,那么每次你增加指针它都会移动一个。如果它是一个int*,那么每个增量都会增加一个以上的指针,通常是 4(由于 int 通常是 32 位,但并非总是如此)。

如果你有一个指向结构的指针,那么递增指针会移动结构的大小。因此sizeof 不应该在那里,否则你会移动太多。

memcpy(dest + (start_position * sizeof(MyEnum)), source, source_size * sizeof(MyEnum));

这会将指针每个位置移动 4*4 字节,因为 MyEnum 是四个字节。

memcpy(dest + start_position, source, source_size * sizeof(MyEnum));

这一次只移动 4 个字节。

这是合乎逻辑的,因为pointer[2]*(pointer + 2) 相同,因此如果指针算法没有隐式考虑指向的类型大小,所有索引也需要sizeof,你最终会写很多pointer[2 * sizeof(*pointer)].

【讨论】:

a[b]*(a+b) 相同。这意味着(a+b) 必须与&a[b] 相同。现在,考虑int a[2];。如果你想要a 的第二个元素,你可以使用a[1] 而不是a[1* sizeof(int)]。这意味着*(a+1),而不是*(a+1*sizeof(int))。因此,对于第二个元素的地址(a+1),而不是(a+1*sizeof(int))。那么,如果你不乘以sizeof(int),为什么还要乘以sizeof(myEnum) 是的,从这个角度来看完全有道理,我只是忘记了经典的*(a+b),只是在考虑字节。太糟糕了,我在这个问题上被否决了,因为这里的答案似乎比重复的答案要好得多。

以上是关于memcpy 中的指针运算有奇怪的结果[重复]的主要内容,如果未能解决你的问题,请参考以下文章

处理numpy数组时赋值运算符中的指针行为?

C语言 | 每日基础(61)

c ++ shared_ptr和memcpy错误[重复]

奇怪的javascript运算符:expr >>> 0 [重复]

指针大小为什么与类型无关

'operator ++(int)&'运算符重载中的'&'是什么意思? [重复]