相对于字符串函数,内存函数像是它们的升级版,不局限于字符类型,任何类型都可使用。
让我们来看看常见的内存函数:memcpy, memmove, memcmp,memset
目录
1. memcpy
此函数能将源地址内的num个元素放入目标地址中,任何类型都可以。
用法如下:
int main()
{
int a1[10] = {1,2,3,4,5,6,7,8,9,10};
int a2[20] = { 0 };
memcpy(a2, a1, 10 * sizeof(int));
int i;
for (i = 0; i < 20; i++)
{
printf("%d ", a2[i]);
}
return 0;
}
1.1 memcpy 模拟实现
由于任何类型都可以,一定要注意强转类型
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);//断言,防止空指针
void* ret = dest;//之后dest会被改变,创造一个空间存储dest的值
while (count--)
{
*(char*)dest = *(char*)src;//由于void不能运算,强转char* 一字节的来进行存储
dest = (char*)dest + 1;//先强转后运算
src = (char*)src + 1;
}
return ret;
}
2. memmove
当想实现下面的这种内存重叠,在一个数组内进行操作,memcpy函数还能实现吗?
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
memcpy(a + 2, a, 16);
int i;
for (i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
答案是有的编译器可以。但是通常情况下,我们遇到这种内存重叠的情况,多使用memmove函数,比memcpy更加安全。
2.1 memmove 模拟实现
要搞懂内存重叠的实现,需要分两种情况
当从前往后传,需要从后往前来进行数据覆盖,相反亦然。
void* my_memmove(void* dest, const void* src, size_t count)
{
void* ret = dest;
//第一种情况:从后往前重叠
if (dest < src)
{
while (count--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
//第二种情况:从前往后重叠
else
{
while (count--)
{
//一字节一字节覆盖,count也在减减
*((char*)dest + count) = *((char*)src + count);
}
return ret;
}
}
3. memcmp
此函数用来比较两块内存中num个元素大小,返回值与strcmp函数相同。
3.1 memcmp 模拟实现
int my_memcmp(const void* dest, const void* src, size_t count)
{
while (count--)
{
if (*(char*)dest == *(char*)src)
{
dest = (char*)dest + 1;
src = (char*)src + 1;
continue;
}
else
return *(char*)dest - *(char*)src;
}
return 0;
}
4. memset
这个函数用于将 dest地址 内 count个地址元素 改为整数c,如下:
int main()
{
int a1[] = { 1, 2, 3, 4, 5 };
memset(a1, 1, 20);
return 0;
}
在内存中的情况:
4.1 memset 模拟实现
void* my_memset(void* dest, int c, size_t count)
{
assert(dest);
void* ret = dest;
while (count--)
{
*(char*)dest = (char)c;
dest = (char*)dest + 1;
}
return ret;
}
感谢你能看到这,如有帮助,希望能点个👍。