memcpy() 和 memset() 的奇怪行为 [关闭]

Posted

技术标签:

【中文标题】memcpy() 和 memset() 的奇怪行为 [关闭]【英文标题】:Strange behaviour of memcpy() and memset() [closed] 【发布时间】:2019-01-07 15:03:07 【问题描述】:

我发现 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)

我做错了吗?

【问题讨论】:

阅读指针算法。如果 destinationS* 你不必乘以大小 array + (sizeof(S) * 1) - 没有做你认为的那样。阅读指针算法。你想要array + 1 array + 8 不会将 8 添加到 array。它增加了 8 S 的大小。在这种情况下,就像(char*)array + 64 很可能不是问题,但声明 _S 的行为未定义。 那么你使用的不是C编译器,而是C++。您可能会发现其他问题。 【参考方案1】:

memcpymemset 不是这种情况下的罪魁祸首。你的问题来自对pointer arithmetic的误解。

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

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

3 x S 6 x int 18 x char(字节)

您希望能够忽略字节,只通过S 访问xy 字段,这样就留下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 *

【讨论】:

是的,你是对的。混淆来自我的假设,即指针只是一个变量,其值是表示地址的数字。因此,当我说“pointer+1”时,我希望这个值会被取值并增加 1 而不是 4(int * 的情况,依此类推)。 @NikolayP。指针只是内存中的一个地址,但在编译时,它的类型是已知的,所以它被考虑在内。在指针运算过程中,它会按其底层类型的大小递增,但指针本身的大小取决于架构(32 位、64 位等)。

以上是关于memcpy() 和 memset() 的奇怪行为 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

MemSet 和 MemCpy

memset memcpy

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

memcpy() memset() 内存拷贝函数 /初始化

裸机嵌入式 C++:将闪存写入 ram 时未定义对 memcpy 和 memset 的引用

strcpy,memcpy,memset函数实现