C语言内存操作函数

memcpy:

void * memcpy ( void * destination, const void * source, size_t num ); 

从source复制数据给dest,注意size_t是字节数,和类型无关。比如可以这样调用:
int main()
{
    int p[3] = { 4,4,4 }, q[3] = { 2,2,2 };
    memcpy(p, q, 3 * sizeof(int));
    return 0;
}

其中要指定3个int的长度,一共复制12个字节。

 

memmove:

void * memmove ( void * destination, const void * source, size_t num );

和memcpy功能相似,但函数内部会防止在复制过程中抹除原位置数据,比如对于一个数组p我们memcpy(p+2,p,5*sizeof(int));可以看到我们复制第一个int时候,把第3个位置的p[2]数据复写了。

 

 

 memmove与memcpy的区别就是可以识别到这种内存重合,在这种情况下从后往前复制数据,这样就不会产生数据复写导致丢数据。

内部实现原理是一个if else语句,对内存是否有重合两种情况分别进行处理。其中查看内存是否重合是用一个宏__np_anyptrlt。c语言实现代码如下:

#include <stddef.h> /* for size_t */
void *memmove(void *dest, const void *src, size_t n)
{
    unsigned char *pd = dest;
    const unsigned char *ps = src;
    if (__np_anyptrlt(ps, pd))
        for (pd += n, ps += n; n--;)
            *--pd = *--ps;
    else
        while(n--)
            *pd++ = *ps++;
    return dest;
}

 

 

memcpr:

void * memcpy ( void * destination, const void * source, size_t num );
比较二者每个字节的大小(按ASCII大小比较,所以'g'是大于'G'的,小写字母大于大写字母)
注:'0':48,'A':65,'a':97

 

 

 

memset:

void * memset ( void * ptr, int value, size_t num );
将ptr之后num个字节填充为value。

 这里有个问题,第二个参数是int,但实际上我们只能使用<256的int。原因是memset实际是:将从ptr开始的num个字节,每个字节都替换为value。

比如:int p[10];

memset(p,1,sizeof(p));

观察内存:确实是每个字节都赋值为1,而不是我们想要的每个int值为1。

 

 也就是说,要么对char*的空间使用memset,可以对其指定任何字符:

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

int main ()
{
  char str[] = "almost every programmer should know memset!";
  memset (str,'-',6);
  puts (str);
  return 0;
}

 要是对其他类型如:int*、float*这样的空间进行memset操作,只能置0,否则最终读出来的int、float值是无意义的。。

 

 





posted @ 2020-03-11 23:36  NeoZy  阅读(526)  评论(0编辑  收藏  举报