memcpy、memset用法总结

深入理解memcpy与memset的用法及内存操作
本文详细介绍了C++中memcpy和memset函数的使用。memcpy用于字节级别的内存复制,避免了直接赋值可能导致的内存泄漏问题;memset则用于设置内存块的每个字节为特定值。示例代码展示了它们的使用场景,并强调了堆内存管理的重要性。同时,文中探讨了为何在某些情况下使用堆分配内存和memcpy优于栈分配和直接赋值。

1. memcpy用法

说来惭愧,虽然有经常在代码里接触到这个函数,一直以为这个函数的作用是复制内存,今天才发现,是复制内存上每个字节上的内容。具体的信息可以查看下官方文章的描述。通过下面这个例子看看情况:

#include <iostream>
#include <string>
#include <cstring>

int main ()
{
  char* data;
  char* tdata;
  data = new char[10];
  tdata = new char[10];
  char* temp = "i am test";
  std::cout << "data memery: " << static_cast<const void *>(data) << std::endl;
  std::cout << "tdata memery: " << static_cast<const void *>(tdata) << std::endl;
  std::cout << "temp memery: " << static_cast<const void *>(temp) << std::endl;


  memcpy(tdata, temp, 10);
  memcpy(data, tdata, 10);

  std::cout << "data memery after memcpy: " << static_cast<const void *>(data) << std::endl;
  std::cout << "tdata memery after mencpy: " << static_cast<const void *>(tdata) << std::endl;
  std::cout << "data content after memcpy: " << data << std::endl;

  tdata = temp;
  std::cout << "tdata memery after assign: " << static_cast<const void *>(tdata) << std::endl;
  std::cout << "data content after assign: " << tdata << std::endl;
}

输出:
在这里插入图片描述

通过上面的输出可以发现,mencpy只是一个个字节的拷贝源指针上的内容到目的指针。

另外,值得注意的是,如果我们直接将一个char* 的变量赋值(assign)给一个另一个char* 时,被赋值的指针地址将被替换。因此,对于从堆上申请的内存,我们不能直接采用赋值的方式,不然会导致内存泄漏,这也是为什么需要用memcpy来拷贝char*变量的内容。

顺便再说下,为什么需要用堆上内存更好,为什么不用栈上的变量,这个我其实不太清楚二者的优劣(内存真的太深奥了。。。),做下可能猜想,如果我们将一个临时变量赋值给本地变量供程序后续使用时(根据上一段的描述我们知道,此时是将临时变量的地址赋给本地变量),将出现临时变量的地址在其生命周期后被销毁后,我们仍在使用这个地址,此时将造成致命的错误,所以采用new(堆)+memcpy的方式会更好。

最后贴一个官方的例子,加深下理解:

/* memcpy example */
#include <stdio.h>
#include <string.h>

struct {
  char name[40];
  int age;
} person, person_copy;

int main ()
{
  char myname[] = "Pierre de Fermat";

  /* using memcpy to copy string: */
  memcpy ( person.name, myname, strlen(myname)+1 );
  person.age = 46;

  /* using memcpy to copy structure: */
  memcpy ( &person_copy, &person, sizeof(person) );

  printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );

  return 0;
}

在这里插入图片描述

2. memset的用法

查看这篇https://blog.youkuaiyun.com/u014174955/article/details/50880202

<think>嗯,用户想了解C语言中memsetmemcpy用法和示例。我需要根据他们提供的引用资料来整理回答。首先,memset的作用是设置内存块的值,通常用于初始化或清零。而memcpy则是复制内存块的内容,不考虑数据类型。 先看memset。引用3中有一个例子,用memset将数组所有元素初始化为0。需要注意的是,memset按字节操作,所以对于非字符类型的数组,比如int,如果设置为1,每个字节都会被设为1,导致每个int元素实际是0x01010101,这可能不是预期的结果。这个点需要强调,避免用户误用。 然后是memcpy。引用1中的示例展示了如何用memcpy覆盖目标字符串的前半部分,结果后面还保留了“as6”。这说明memcpy不会自动添加终止符,所以处理字符串时要小心,可能需要手动添加'\0'。引用2的例子显示memcpy拷贝int数组时,遇到'\0'(即0)也不会停止,因为它处理的是字节,不是字符串。所以用户需要知道memcpy的参数是字节数,计算时要准确,比如int数组要乘以sizeof(int)。 另外,引用4提到memcpymemset的区别,一个是复制内存,一个是设置内存。这点要明确分开。还要提醒用户注意内存重叠的问题,这时候应该用memmove而不是memcpy,避免未定义行为。 用户可能需要具体的示例来理解这两个函数。根据引用资料里的代码,我可以整理出几个例子,比如用memset初始化数组为零,用memcpy复制数组的一部分。同时,要指出常见的错误,比如错误的字节数计算,或者对非字符类型使用memset的错误值。 最后,生成相关问题的时候,可以考虑内存重叠的处理、与strcpy的区别、常见错误等,帮助用户进一步学习。确保回答结构清晰,先用法说明,再示例,注意事项,最后相关问题。记得引用对应的引用资料,比如在注意事项中提到内存覆盖的问题引用2和4。</think>### C语言中`memset`和`memcpy`的用法详解 #### 一、`memset`的用法 `memset`用于将内存块的每个字节设置为特定值,常用于初始化或清零操作。 - **语法**:`void *memset(void *dest, int value, size_t count);` - `dest`:目标内存地址 - `value`:设置的字节值(实际以`unsigned char`处理) - `count`:设置的字节数 **示例1:初始化数组为0** ```c #include <stdio.h> #include <string.h> int main() { int arr[5]; memset(arr, 0, sizeof(arr)); // 将arr所有字节设为0 for (int i = 0; i < 5; i++) { printf("%d ", arr[i]); // 输出: 0 0 0 0 0 } return 0; } ``` **注意**: - `memset`按字节操作,若对`int`数组设置非0值(如`memset(arr, 1, sizeof(arr))`),每个`int`元素的每个字节会被设为`0x01`,实际值为`0x01010101`,而非`1`[^3]。 --- #### 二、`memcpy`的用法 `memcpy`用于从源内存地址复制指定字节到目标地址,适用于任意数据类型。 - **语法**:`void *memcpy(void *dest, const void *src, size_t count);` - `dest`:目标内存地址 - `src`:源内存地址 - `count`:复制的字节数 **示例2:复制字符串的一部分** ```c #include <stdio.h> #include <string.h> int main() { char src[] = "******************************"; char dest[] = "abcdefghijlkmnopqrstuvwxyz0123as6"; printf("Before: %s\n", dest); // Before: abcdefghijlkmnopqrstuvwxyz0123as6 memcpy(dest, src, strlen(src)); // 复制src的前strlen(src)字节到dest printf("After: %s\n", dest); // After: ******************************as6 return 0; } ``` **示例3:复制整型数组** ```c #include <stdio.h> #include <string.h> int main() { int arr1[] = {1, 2, 3, '\0', 4, 5, 6, 7, 8, 9, 10}; int arr2[10] = {0}; memcpy(arr2, arr1, 24); // 复制24字节(6个int元素) for (int i = 0; i < 10; i++) { printf("%d ", arr2[i]); // 输出: 1 2 3 0 4 5 0 0 0 0 } return 0; } ``` **注意**: - `memcpy`不检查内存重叠,若目标与源地址重叠,需改用`memmove`[^4]。 - 若操作字符串,需手动添加终止符`\0`[^1]。 --- #### 三、关键区别 | 函数 | 作用 | 是否处理`\0` | 适用场景 | |---------|--------------------|--------------|------------------------| | `memset`| 设置内存块的值 | 否 | 初始化、清零内存 | | `memcpy`| 复制内存块内容 | 否 | 任意类型数据拷贝 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值