本章介绍内存函数
- memecpy
- memmove
- memcmp
- memset
1. memcpy
- 函数
memcpy
从source
的位置开始向后复制num个字节的数据到destination
的内存位置 - 这个函数在遇到
'\0'
的时候并不会停下来 - 如果
source
和destination
有任何的重叠,复制的结果是未定义的(重叠时需要使用memmove
)
memcpy
函数的参数是void*,返回值也是void*
代码示例
/* memcpy example */
#include <stdio.h>
#include <string.h>
struct {
char name[40];
int age;
} person, person_copy;
int main ()
{
char myname[] = "Pierre de Fermat";
/* using memcpy to copy string: */
memcpy ( person.name, myname, strlen(myname)+1 );//拷贝字符串
person.age = 46;
/* using memcpy to copy structure: */
memcpy ( &person_copy, &person, sizeof(person) );//拷贝整形
printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );
return 0;
}
模拟实现
/*模拟memcpy*/
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* cur = dest;
while (num--) //循环num次
{
*(char*)dest = *(char*)src;//强转为char*,一次更改一个字节
//跳过一个字节
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return cur;
}
dest与src数组不可以有重叠的部分
为什么得到的结果与我们想要的不一样呢?不妨画图分析一下
注:虽然有的编译器可以通过memcpy来实现拷贝有重叠内容的内存,但是标准没有这么规定,因此可不可行取决于编译器
希望拷贝有重叠部分的内容,需要使用memmove
2. memmove
memmove
和memcpy
的区别就是memmove
的源内存块和目标内存块是可以重叠的- 如果源内存块和目标内存块出现重叠,就需要使用
memmove
函数处理
代码示例
使用memmove
可以得到想要的正确结果
模拟实现
当dest与src无重叠部分,从前往后拷贝或者从后往前拷贝都可以,因此只需要讨论dest有重叠的情况
char* my_memmove(char* dest, const char* src, size_t num)
{
assert(dest && src);
void* cur = dest;
if (dest < src)
{
/*从前往后拷贝*/
while (num--) //循环num次
{
*(char*)dest = *(char*)src;//强转为char*,一次更改一个字节
//跳过一个字节
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return cur;
}
else
{
/*从后往前拷贝*/
while (num)
{
*((char*)dest + num - 1) = *((char*)src + num - 1);//从后开始解引用
num--;
}
return src;
}
return cur;
}
3. memset
- memset是以字节为单位设置值
代码示例
0x1010101对应的十进制就是16843009
模拟实现
//模拟实现memset
void* my_memset(void* dest, int val, size_t num)
{
assert(dest);
void* cur = dest;
while (num--)
{
*(char*)dest = val;
dest = (char*)dest + 1;
}
return cur;
}
4. memcmp
- 函数不会因为遇见结束符而停止比较
- 比较是以字节为单位
代码示例
int main()
{
int a = 0x11223344;
int b = 0x11224411;
if (memcmp(&a, &b, 1) > 0)
{
puts("The First Byte of a > The First Byte of b!");
}
else if (memcmp(&a, &b, 1) < 0)
{
puts("The First Byte of a < The First Byte of b!");
}
else puts("The First Byte of a = The First Byte of b!");
return 0;
}
a比b小,但是由于小端存储,a的低地址处的第一个字节小于b的低地址处的第一个字节,
memcmp
是以字节为单位进行比较,因此返回结果<0
模拟实现
//模拟实现memcmp
int my_memcmp(const void* str1, const void* str2, size_t num)
{
while (num--)
{
if ((char*)str1 != (char*)str2) return (char*)str1 - (char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
return 0;
}