mem 族函数的实现
1.void * memcpy ( void * dest, const void * src, size_t num );
头文件:#include <string.h>
memcpy() 用来复制内存,memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上。
memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。
需要注意的是:
- dest 指针要分配足够的空间,也即大于等于 num 字节的空间。如果没有分配空间,会出现断错误。
- dest 和 src 所指的内存空间不能重叠(如果发生了重叠,使用 memmove() 会更加安全)。
与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“\0”而结束。
【返回值】返回指向 dest 的指针。注意返回的指针类型是 void,使用时一般要进行强制类型转换。
void* Memcpy(void* dst,const void* src, int n) { if (dst == NULL || src == NULL) { return dst; } void* result = dst; while (n--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } return result; }
2.void* memmove(void* dst, const void* src, size_t n)
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
void* Memmove(void* dst,const void* src, int n) { if (dst == NULL || src == NULL || dst == src) //不用拷贝 { return dst; } char* m_dst = (char*)dst; char* m_src = (char*)src; if (m_dst > m_src && m_dst < m_src + n) //反向拷贝 { m_dst = m_dst + n - 1; m_src = m_src + n - 1; while (n--) { *m_dst-- = *m_src--; } } else //正向拷贝 { while (n--) { *m_dst++ = *m_src++; } } return dst; }
3.memcmp
头文件:#include <string.h>
定义函数:int memcmp (const void *s1, const void *s2, size_t n);
函数说明:memcmp()用来比较s1 和s2 所指的内存区间前n 个字符。
字符串大小的比较是以ASCII 码表上的顺序来决定,次顺序亦为字符的值。memcmp()首先将s1 第一个字符值减去s2 第一个字符的值,若差为0 则再继续比较下个字符,若差值不为0 则将差值返回。例如,字符串"Ac"和"ba"比较则会返回字符'A'(65)和'b'(98)的差值(-33)。
返回值:若参数s1 和s2 所指的内存内容都完全相同则返回0 值。s1 若大于s2 则返回大于0 的值。s1 若小于s2 则返回小于0 的值。
int Memcmp(const void *s1, const void *s2, size_t n) { assert(s1 && s2); char* m_s1 = (char*)s1; char* m_s2 = (char*)s2; while (n--) { if (*m_s1 - *m_s2) { return *m_s1 - *m_s2; } else { m_s1++; m_s2++; } } return 0; }
4.memset
memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为:
void * memset( void * ptr, int value, size_t num );
参数说明:
- ptr 为要操作的内存的指针。
- value 为要设置的值。你既可以向 value 传递 int 类型的值,也可以传递 char 类型的值,int 和 char 可以根据 ASCII 码相互转换。
- num 为 ptr 的前 num 个字节,size_t 就是unsigned int。
【函数说明】memset() 会将 ptr 所指的内存区域的前 num 个字节的值都设置为 value,然后返回指向 ptr 的指针。
memset() 可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。例如:
- char str[20];
- memset(str, '\0', sizeof(str)-1);
【返回值】返回指向 ptr 的指针。
注意:参数 value 虽声明为 int,但必须是 unsigned char,所以范围在0 到255 之间。
void * Memset(void * ptr, int value, size_t num) { assert(ptr); char* m_ptr = (char*)ptr; while (num--) { *(m_ptr++) = value; } return ptr; }