我发现MSVC2017中的memcpy()和memset()函数有些奇怪,我无法解释。具体来说,“目标”不是按单个字节索引,而是按结构的整个大小(“ size”参数)进行索引。
所以我有一个结构:
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)
我做错什么了吗?
答案 0 :(得分:2)
memcpy
和memset
在这种情况下不是罪魁祸首。您的问题来自对pointer arithmetic的误解。
将数字添加到指针时,指针前进的元素数要多,而不是字节数要多。因此,如果sizeof(S) == 8
,则指向S
的指针在添加1时会前进8字节,在添加2时会前进16字节,依此类推。关键是您可以从图片中提取字节(以及元素的大小)。
因此,如果您分配了由三个S
元素组成的数组,则内存的布局可能会像这样:
S
int
char
(字节)您希望能够忽略字节,而仅通过x
访问y
和S
字段,从而留下S
大小的内存块
|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 *