前言:
通过C语言进阶前篇的字符串函数的知识,继续C语言的内存函数学习。
/知识点汇总/
内存相关的函数
1.memcpy – strcpy —仅仅是操作字符串进行拷贝,而memcpy内存中的数据,不仅仅是操作字符
2.memmove
3.memset
4.memcmp — strcmp
原型:void *memcpy( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
头文件:
功能:将源头内存的数据。拷贝到目标内存中
注意:与strncpy不同的是,参数num和count。一个是指需要拷贝的元素个数,一个是指需要拷贝的元素字节大小
#include
#include
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5 };
memcpy(arr1, arr2, 20);//20 == 4*5
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
#include
#include
#include
//注意:void* 不能进行运算操作
//另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
{
assert(dest && src);
while (sz--)//以一个字节一个字节的拷贝
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
src = (char*)src + 1;
}
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5 };
my_memcpy(arr1, arr2, 20);//20 == 4*5
for (int i = 0; i < 5; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
扩展:memcpy对同一内存空间的操作问题
#include
#include
#include
//注意:void* 不能进行运算操作
//另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
{
assert(dest && src);
void* ret = dest;
while (sz--)//以一个字节一个字节的拷贝
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//my_memcpy(arr+2, arr, 20);//20 == 4*5
//模拟的memcpy达不到预期的要求
memcpy(arr + 2, arr, 20);
//发现库函数的memcpy可以实现要求
for (int i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
小结:
1.memcpy只能对不同空间内存之间的数据进行操作
即:不重叠内存的拷贝,可以使用memcpy,而重叠的内存空间则需要用memmove函数
2.库函数可以实现,标准规定:
以memcpy来实现不重叠的内存的拷贝,且要求能达到60即可,以memmobe来实现重叠内存的拷贝
3.但是,发现当前的编译环境下,memcpy同样能实现重叠内存的拷贝,远远满足60分的要求,100分
所以于编译环境相关,建议相应的功能交给适合的函数实现即可。
原型:void *memmove( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
头文件:
功能:将源头内存的数据。拷贝到目标内存中,且与memcpy相比可以拷贝同一空间的数据
#include
#include
int main()
{
//int arr1[10] = { 0 };
//int arr2[] = { 1,2,3,4,5 };
//memmove(arr1, arr2, 20);//20 == 4*5
//int sz = sizeof(arr1) / sizeof(arr1[0]);
//for (int i = 0; i < sz; i++)
//{
// printf("%d ", arr1[i]);
//}
int arr[] = { 1,2,3,4,5,6,7,8,9,10};
memcpy(arr+2, arr, 20);//20 == 4*5
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
#include
#include
void* my_memmove(void* dest, const void* src, size_t sz)
{
assert(dest && src);
char* ret = (char*)dest;
if (dest < src)//从前向后拷贝
{
while (sz--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//从后向前拷贝
{
while (sz--)//sz-- 先用再减,即先判断sz=20为真,用完后减1进入循环,此时sz=19
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr + 2, arr, 20);//20 == 4*5
//my_memmove(arr, arr + 2, 20);//20 == 4*5
//my_memmove(arr, arr + 5, 20);//20 == 4*5
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
原型:void *memset( void *dest, int c, size_t count );
头文件:
功能:是设置内存的,并且以字节为单位设置的
#include
#include
int main()
{
char arr[] = "hello world";
memset(arr+6, 'H', 4);
printf("%s\n", arr);
return 0;
}
建议:以字节为单位设置的,所以更合适字符,但是设置为0可以是任意类型
原型:int memcmp( const void *buf1, const void *buf2, size_t count );
头文件:
功能:是比较两个内存块,并且是以字节为单位的方式进行比较的
返回值:
*buf1 > *buf2 — 返回>0的值
*buf1 = *buf2 — 返回=0的值
*buf1 < *buf2 — 返回<0的值
#include
#include
int main()
{
//int arr1[] = { 1,2,3,4,5,6,7 };
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
//int arr2[] = { 1,2,3,7 };
01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
//int ret = memcmp(arr1, arr2, 12);//精确到字节比较
//printf("%d\n", ret);//0 --- 前12位相同
//int arr1[] = { 1,2,3,4,5,6,7 };
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
//int arr2[] = { 1,2,3,7 };
01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
//int ret = memcmp(arr1, arr2, 13);//精确到字节比较
//printf("%d\n", ret);//-1 ---第十三位: 04 < 07
int arr1[] = { 1,2,3,4,5,6,7 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
int arr2[] = { 1,2,3,0x11223304 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 33 22 11
int ret = memcmp(arr1, arr2, 13);//精确到字节比较 --- 前13位相同 0
//int ret = memcmp(arr1, arr2, 14);//精确到字节比较 --- 第14位 00 < 33 --- -1
printf("%d\n", ret);
return 0;
}
熟悉各个函数的使用有利于程序的可读性和效率,此篇笔记有误的地方请多多指教。
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)