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值是无意义的。。
进击的小🐴农