void * memcpy ( void * dest, const void * src, size_t num )
(1)函数memcpy从src的位置开始向后复制num个字节的数据到dest的内存位置。
(2)这个函数在遇到’\0’ 的时候并不会停下来。
(3)如果src和dest有任何的重叠,复制的结果都是未定义的 。
void *my_memcpy(void *dest, const void *src, size_t num)
{
char *str1 = (char *)dest;//应为此函数要将src的n个字节copy给dest
char *str2 = (char *)src;//所以先强转为char*
assert(dest != NULL && src != NULL);//使用assert断言,防止传空指针
while (num--)
{
*str1++ = *str2++;//切记不能把此条语句放入while()中,其他类型强转成char*
}//时之间可能会存有'\0'的字节,会导致while的结束
return dest;
}
int main()
{
int ar[10] = { 1, 2, 3, 4 };
int ar2[10];
my_memcpy(ar2, ar, 4);
printf("%d %d\n", ar2[0], ar2[1]);
system("pause");
return 0;
}
void * memmove ( void * dest, const void * src, size_t num )
(1).和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
(2).如果源空间和目标空间出现重叠,就得使用memmove函数处理
void *my_memmove(void * dest, const void * src, size_t num)
{
char *str1 = (char*)dest;//定一两个char*指向要处理的两个字符串的首地址
char *str2 = (char*)src;//memmove是字节移动函数,必须强转为char*;
assert(str1 != NULL&&str2 != NULL);//遇见指针先断言
if (str1 <= str2 || str1 >= str2 + num)
//以下就是对于内存重叠时和memcpy的不同之处,
{//分为三种情况,第一种:src在低地址(一串字符串从左到右地址由高到低),dest在高地址
//从左到右一次移动就好,不会发生内存重叠。第二种:src在高地址,dest在低地址,
//但要移动的长度不足以使其反生内存重叠。
*str1++ = *str2++;
}
else
//第三种:src在高地址,dest在低地址,移动的长度正好会发生内存重叠
{//解决方法就是由原来的从左到右移动改为从右向左移动,先把内存重叠区域的
//字符移动走,就不会被高地址的覆盖掉。
str1 += num - 1;//str1和str2先移动到内存重叠区域的最后一个字符上
str2 += num - 1;
while (num--)
{//依次从左向右赋值
*str1-- = *str2--;
}
}
}
int main()
{
char ar1[10] = "abcdef";
char ar2[10] = "abcdef";
char ar3[10] = "abcdef";
char ar4[10] = "abcdef";
my_memmove(ar1+2, ar1, 4);
printf("my_memmove ar1 = %s\n", ar1);
my_memmove(ar2, ar2+2, 4);
printf("my_memmove ar2 = %s\n", ar2);
my_memcpy(ar3, ar3 + 2, 4);
printf("my_memcpy ar3 = %s\n",ar3);
my_memcpy(ar4 + 2, ar4, 4);
printf("my_memcpy ar4 = %s\n", ar4);
system("pause");
return 0;
}
运行结果:
由此可以看出,在对自身进行字符串处理时,遇到内存重叠,使用memcpy会更符合意想的结果。
**void memset( void dest, int c, size_t count )
The memset function sets the first count bytes of dest to the
character c .
memset函数将dest的前count个字节全部设置为字符c。
void *my_memset(void *dest, int value, size_t count)
{
char *tmp = (char*)dest;
assert(tmp != NULL);
while (count--)
{
*tmp++ = value;
}
return dest;
}
int main()
{
char ar1[10] = "abcdef";
my_memset(ar1, 'o', 4);
printf(ar1);
system("pause");
return 0;
}
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
1.比较从ptr1和ptr2指针开始的num个字节
2.返回值如下
返回值 | ptr1 ? ptr2 |
---|---|
1 | > |
0 | = |
-1 | < |
注意:strcmp,strncmp和memcmp的比较
1、比较的内容不同。strcmp和strncmp只能比较字符串,而memcmp可以比较字符串,字符数组,数组等。
2、比较的方法不同。strcmp和strncmp(’\0’和num同时限制)遇到被复制字符的串结束符"\0"才结束,所以容易溢出。对于memcmp(),如果两个字符串相同而且num大于字符串长度的话,memcmp不会在\0处停下来,会继续比较\0后面的内存单元,直到ret不为零或者达到num次。(注:库函数中strncmp不会在’\0’处停下来)
int my_memcmp(const void * ptr1, const void * ptr2, size_t num)
{
unsigned char* str1 = (unsigned char*)ptr1;
unsigned char* str2 = (unsigned char*)ptr2;
int ret;
if (!num)
{
return 0;
}
assert(str1 != NULL && str2 != NULL);
while ((num--) && !(ret = (*str1 - *str2)))//与strcmp最大的差别,不用找'\0'
{
str1++;
str2++;
}
if (ret > 0)
{
return 1;
}
else if (ret < 0)
{
return -1;
}
return 1;
}
int main()
{
char ar1[10] = "abcdef";
char ar2[10] = "abcd";
printf("%d\n", my_memcmp(ar1, ar2, 5));
printf("%d\n", my_strncmp(ar1, ar2, 5));
system("pause");
return 0;
}