首页 > 解决方案 > memcpy() 和 memset() 的奇怪行为

问题描述

我发现 MSVC2017 中的 memcpy() 和 memset() 函数有些奇怪,我无法解释。具体来说,“目标”不是按单个字节索引,而是按结构的整个大小(“大小”参数)索引。

所以我有一个结构:

typedef struct _S
{
    int x;
    int y;
} S;

代码如下:

S* array = (S*)malloc(sizeof(S) * 10); /* Ok. Allocates enough space for 10 structures. */

S s; /* some new structure instance */

/* !!! here is the problem. 
 * sizeof(S) will return 8
 * 8*1 = 8
 * now the starting address will be: array+8
 * so I'm expecting my structure 's' to be copied to
 * the second ''element'' of 'array' (index 1)
 * BUT in reality it will be copied to the 7th index! 
 */
memcpy(array + (sizeof(S) * 1), &s, sizeof(S));  

/* After some tests I found out how to access 'properly' the 
 * 'array': 
 */
memcpy(array + 1, &s, sizeof(S); /* this will leave the first struct
    in the 'array' unchanged and copy 's's contents to the second 
    element */

memset() 也一样。到目前为止,我认为应该手动完成索引,同时提供复制对象的大小,但不是吗?

memcpy(destination + (size * offset), source + (size * offset), size)

难道我做错了什么?

标签: cvisual-c++memcpymemset

解决方案


memcpy并且memset不是本案的罪魁祸首。您的问题来自对指针算术的误解。

当您将数字添加到指针时,指针会前进那么多元素,而不是那么多字节。因此,如果sizeof(S) == 8,则指向 an 的指针S在加 1 时前移 8 个字节,在加 2 时前移 16 个字节,依此类推。关键是您可以从图片中抽象出字节(以及元素的大小)。

因此,如果您分配了一个包含三个元素的数组S,您的内存可能会像这样布置:

  • S
  • int
  • 18 x char(字节)

您希望能够忽略字节,并且只通过 访问xandy字段S,以便留下S-size 的内存块。

|0              |1              |2              | array            : S *
|x       y      |x       y      |x       y      | S[N]->x, S[N]->y : int *
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7| individual bytes : char *

推荐阅读