C语言内存函数
文章目录
- 1. memcpy函数
- 1.1使用规则
- 1.2memcpy函数的模拟实现
- 2.memmove函数
- 2.1使用规则
- 2.2memmove函数的模拟实现
- 3.memset函数
- 4.memcmp函数
1. memcpy函数
1.1使用规则
void *memcpy ( void *destination, const void *source, size_t num );
- 将source指向的源内存区域中指定字节数(num)的数据复制到destination指向的目标内存区域
- 遇 ‘\0’ 不会停下
- 源内存区域和目标内存区域有重叠可能产生未定义行为
- 当源内存区域和目标内存区域有重叠时,建议使用 memmove 函数,它可以正确处理内存重叠的情况
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);
// int 类型通常占 4 个字节,所以 20 字节相当于 5 个 int 元素
// 因此这里将 arr1 的前 5 个元素复制到 arr2 的前 5 个位置
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
1.2memcpy函数的模拟实现
#include <stdio.h>
#include <assert.h>
// 参数 dst 是目标内存区域的起始地址
// 参数 src 是源内存区域的起始地址
// 参数 count 是要复制的字节数
void* memcpy(void* dst, const void* src, size_t count)
{
void* ret = dst;
assert(dst);
assert(src);
/* 从低地址向高地址复制数据 */
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return(ret);
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[5];
memcpy(arr2, arr1, sizeof(arr1));
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
return 0;
}
2.memmove函数
2.1使用规则
当源内存区域和目标内存区域有重叠时,建议使用 memmove 函数
void *memmove ( void *destination, const void *source, size_t num );
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
// arr1 的前 5 个元素复制到 arr1 的第 3 个位置开始往后的 5 个位置
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
2.2memmove函数的模拟实现
#include <stdio.h>
#include <assert.h>
void* memmove(void* dst, const void* src, size_t count)
{
void* ret = dst;
assert(dst != NULL);
assert(src != NULL);
// 情况一:目标内存区域在源内存区域之前,或者目标内存区域在源内存区域之后且不重叠
if (dst <= src || (char*)dst >= ((char*)src + count))
{
/* 从低地址向高地址复制数据 */
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
// 情况二:目标内存区域和源内存区域存在重叠,且目标内存区域在源内存区域之后
else
{
/* 从高地址向低地址复制数据 */
// 将目标内存地址移动到要复制的最后一个字节的位置
dst = (char*)dst + count - 1;
// 将源内存地址移动到要复制的最后一个字节的位置
src = (char*)src + count - 1;
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
return(ret);
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
3.memset函数
memset 函数用于将指定内存区域的前若干个字节设置为指定的值,常用于初始化内存或清空内存。
void *memset ( void *ptr, int value, size_t num );
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "hello world";
memset(str, 'x', 6); // 将str数组的前 6 个字节填充为字符 'x'
printf("%s", str);
return 0;
}
4.memcmp函数
int memcmp ( const void *ptr1, const void *ptr2, size_t num );
- 比较ptr1和ptr2指针指向的位置开始,向后的num个字节
- 根据比较结果返回小于、等于或大于 0 的整数,以此判断两个内存区域内容的大小关系
- 直到比较完 num 个字节或发现不同
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0)
printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0)
printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else
printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}