内存函数操作
memcpy
memcpy指的是C和C++使用的内存拷贝函数,函数原型为:void *memcpy(void *destin, void *source, unsigned n);
函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中。
中文名
内存拷贝函数
外文名
memcpy
功能
拷贝n个字节
所需头文件
C语言:#include<string.h>
#include<stdio.h>
#include<string.h>
void test1()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[8] = { 0 };
memcpy(arr2, arr1, 20);
}
void test2()
{
float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f };
float arr2[8] = { 0 };
memcpy(arr2, arr1, 20);
}
int main()
{
test1();
test2();
return 0;
}
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (num--)
{
*(char*)dest = *(char*)src;
dest = *(char*)dest + 1;
src = *(char*)src + 1;
}
return ret;
}
void test3()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[8] = { 0 };
my_memcpy(arr2, arr1, 20);
}
int main()
{
test3();
return 0;
}
注意:strcpy和memcpy主要有以下3方面的区别。
【
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
memmove
memmove()函数用于:移动内存块
函数介绍
函数声明:void * memmove ( void * destination, const void * source, size_t num );
参数:
目的地:指向要在其中复制内容的目标数组的指针,类型转换为 void* 类型的指针。
源:指向要复制的数据源的指针,类型转换为 const void* 类型的指针。
返回值: 返回目的地。
头 文 件:#include <string.h>
#include <stdio.h>
#include <string.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
if (dest < src)
{
//前->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = *(char*)dest + 1;
src = *(char*)src + 1;
}
}
else
{
//后->前
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
void test4()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+2, arr1, 40);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
}
int main()
{
test4();
return 0;
}
memmove和memcpy的区别:
memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;
如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。
memcpy的效率会比memmove高一些。
memset
作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
别名:初始化函数
表达式:memset(void *s,int ch,size_t n);
头文件:string.h
函数:void *memset
原型:(void *s,int ch,size_t n);
样例:memset(fact, 0, sizeof(fact));
#include <stdio.h>
#include <string.h>
void test6()
{
int arr[10] = { 0 };
memset(arr, 1, sizeof(arr));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%p\n", arr[i]);
//这种写法没办法把每个数组元素设置为1
}
return 0;
}
int main()
{
test6();
return 0;
}
常见错误
第一:memset函数按字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。
第二:memset(void *s, int ch,size_t n);中ch实际范围应该在0~~255,因为该函数只能取ch的后八位赋值给你所输入的范围的每个字节,比如int a[5]赋值memset(a,-1,sizeof(int )*5)与memset(a,511,sizeof(int )*5) 所赋值的结果是一样的都为-1;因为-1的二进制码为(11111111 11111111 11111111 11111111)而511的二进制码为(00000000 00000000 00000001 11111111)后八位都为(11111111),所以数组中每个字节,如a[0]含四个字节都被赋值为(11111111),其结果为a[0](11111111 11111111 11111111 11111111),即a[0]=-1,因此无论ch多大只有后八位二进制有效,而后八位二进制的范围在(0~255)中改。而对字符数组操作时则取后八位赋值给字符数组,其八位值作为ASCII码。第三: 搞反了 ch 和 n 的位置.
一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));
而不是 memset(a,20*sizeof(char),0);
memcmp
memcmp语法
函数原型:
int memcmp(const void *str1, const void *str2, size_t n);
参数:
str1-- 指向内存块的指针。
str2-- 指向内存块的指针。
n-- 要被比较的字节数。
功能:比较内存区域buf1和buf2的前count个字节。
头文件:
#include <string.h>或#include<memory.h>
返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。
该函数是按字节比较的。
见代码:
#include<string.h>
#include<stdio.h>
int main()
{
char *s1 = "Hello,Programmers!";
char *s2 = "Hello,Programmers!";
int r;
r = memcmp(s1,s2,strlen(s1));
if(!r)
printf("s1 and s2 are identical\n");/*s1等于s2*/
elseif(r<0)
printf("s1 is less than s2\n");/*s1小于s2*/
else
printf("s1 is greater than s2\n");/*s1大于s2*/
return 0;
}
#include <stdio.h>
#include <string.h>
void test5()
{
int arr1[] = { 1,2,3,4,5 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
int arr2[] = { 1,2,3,4,6 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00
int ret = memcmp(arr1, arr2, 17);
printf("%d\n", ret);
}
int main()
{
test5();
return 0;
}