memcpy

memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h>, 在C++中需要包含的头文件是#include其函数原型如下:

void *memcpy(void *dest, const void *src, size_t n);

其功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

  • 库函数中的memcpy不能处理src和dest有重叠的情况。

clipboard.png

clipboard.png

memmove

memmove和memcpy函数一样,使用时需要包含C++的#include头文件。它与memcpy的功能相似,都是将src所指的n个字节复制到dest所指的内存地址起始位置中,但该函数可以处理src和dest有重叠的情况。实际上,memcpy可以看作是memmove的子集。

memset

函数原型如下:

 void *memset(void *s, int ch, size_t n);

该函数的功能是将s中的前n个字节用ch替换,并返回s

  • memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

在程序中给数组初始化时,常常会用到memset函数,一般的写法如下:

int a[2];
memset(a, 0, sizeof(a));
memset(a, 0, 2*sizeof(int));

需要注意的是,赋值是逐字节进行的:

  • 若s指向char型地址,ch可为任意字符值;
  • 若s指向非char型,如int型地址,要想赋值正确,ch的值只能是-1或0,因为-1和0转化成二进制后每一位都是一样的

错误的赋值例子如下:

int a[2];
memset(a, 1, 2*sizeof(int));
cout << *a << endl;
输出结果为16843009,十六进制为01010101.

strcpy

该函数在C的标准库函数,包含在头文件#include<string.h>和#include<stdio.h>中
函数原型如下:

- char strcpy(char *dest, const char *src);

函数功能是把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间,返回指向dest的指

  • src和dest所指内存区域不可以重叠dest必须有足够的空间来容纳src的字符串。

strcpy和memcpy主要有以下3方面的区别

  • 复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
  • 复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
  • 用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。

总结

  • 对于内存操作的一些列函数来说,其参数返回类型都是 void* ,而不是某种具体的类型,这样是为了任何类型的指针都可以传入memcpy和memset中,都能正确赋值。这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型。

代码分析

#include <iostream>
using namespace std;

int main()
{
    char a[10] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
    cout << a << endl;
    //用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'\0'。
    char b[10] = "012345678";

    char c[10];
    
    memcpy(c, b, sizeof(b));
    cout << c << endl; 
    
    memmove(c, b, sizeof(b));
    cout << c << endl;
    
    memset(c, 0, sizeof(b));
    cout << c << endl;
    
    strcpy_s(c, b);
    cout << c << endl;

    system("pause");
    return 0;
}

输出:(cout会遇到第一个null停止)
0000000000烫烫烫uGX鵖
012345678
012345678

012345678

燃烧你的梦
238 声望17 粉丝