在介绍 m e m c p y memcpy memcpy函数 的功能前,我们先来对函数名进行分析:
m e m mem mem 表示的是 m e m o r y memory memory,它有记忆 、内存 的意思,这里它表示的是内存
c p y cpy cpy 即 c o p y copy copy,表示拷贝
这样我们从名字就能大体知道这个函数的大致功能啦,像之前的 s t r c p y strcpy strcpy函数,它是实现对字符串的拷贝,而 m e m c p y memcpy memcpy函数,实现的是对内存块的拷贝。
(2)函数介绍
功能:将源字符串的前 n u m num num 个内存块内容拷贝到目标字符串中
函数 m e m c p y memcpy memcpy 从 s o u r c e source source 的位置开始向后复制 n u m num num 个字节的数据到 d e s t i n a t i o n destination destination 指向的内存为止
函数的使用需包含头文件 < s t r i n g . h > <string.h> <string.h>
因为拷贝的数据不一定是字符串,函数在遇到 '\0' 时不会停下来
如果 s o u r c e source source 和 d e s t i n a t i o n destination destination 有任何的重叠,复制的结果都是未定义的
d e s t i n a t i o n destination destination 所指向的空间必须足够大,至少 n u m num num 个字节大小,以避免溢出
返回值是目标空间的地址
注:对于重叠的内存,交给 m e m m o v e memmove memmove函数 来处理。
1.2、函数的使用
例如:我们将整型数组 a r r 1 arr1 arr1 的前 5 个元素复制给 a r r 2 arr2 arr2 数组
代码如下:
c复制代码
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
return 0;
}
运行结果:
可能有些小伙伴在调用 m e m c p y memcpy memcpy 函数时, n u m num num 的传参会写成 5 :memcpy(arr2, arr1, 5);,这里需要注意: m e m c p y memcpy memcpy 拷贝是内存块为单位,即字节,而不是要拷贝的元素的个数。
当然, n u m num num 的传参也可以写成 元素个数 ∗ * ∗ s i z e o f sizeof sizeof(类型)
如:上述代码调用 m e m c p y memcpy memcpy 函数可写成:memcpy(arr2, arr1, 5*sizeof(int));
那如果用 m e m c p y memcpy memcpy 拷贝重叠空间会怎样呢?我们用自己写的模拟函数试一下
c复制代码
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
return 0;
}
运行结果:
为什么会这样呢?具体原因稍后解释。
1.3、函数的模拟实现
m e m c p y memcpy memcpy函数 的实现思路和 s t r c p y strcpy strcpy 的实现差不多,即逐一拷贝每个内存块(详情请看:【C语言】------字符串函数的使用与模拟实现(上))
参数用 v o i d void void* 的原因: m e m c p y memcpy memcpy 拷贝的是任意类型的数据,而函数事先并不知道你所用传递的数据的类型,因此用 v o i d void void * 指针,以便能接收所有类型的数据。
assert(dest && src);断言,后面要对指针进行解引用,因此不能传入空指针。
while (num--)循环条件的判断, n u m num num 不为 0,即为真,进入循环,后 n u m num num 自减
*(char*)dest = *(char*)src;【C语言】------ 指针一 : 初识指针(上)一文中,曾提到不能对 v o i d void void * 指针进行解引用操作,因此要改变其所指向的值,要对其进行强制类型转换。因为 c h a r char char * 类型一次的访问权限只有一个字节,因此将其强转成 c h a r char char* 类型,再进行解引用、赋值
这段代码从前往后 的情况与 m e m c p y memcpy memcpy 情况相同,就不再过多解释,来看从后往前的情况
while (num--)这里循环判断条件与上面一样,当 n u m num num 大于 0,进入循环,随后进行自减。
*((char*)dest + num) = *((char*)src + num);这里我们发现,如果要拷贝 20 字节内容,即 n u m num num 等于 20,那么起始位置加 n u m num num - 1 所指向的就是最后一个要拷贝的字节,而 n u m num num 在进入循环后已经自减,因此这里直接加 n u m num num 。再接着,再次循环, n u m num num 再次自减,拷贝倒数第二个字节内容,以此类推,直至 n u m num num 为 0 拷贝结束。
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10];
memset(arr, 0, 10*sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
运行结果:
那又有小伙伴问全部设置成 1 可以吗?我们来试试
c复制代码
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10];
memset(arr, 1, 10*sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
运行结果:
为什么会这样?
我们要注意: m e m s e t memset memset 是以字节为单位来设置的。
1 的二进制是 00000000 00000000 00000000 00000001
而 m e m s e t memset memset 是将每个字节单独设置成 1,即一个整型被设置成:00000001 00000001 00000001 00000001,转换成二进制即:16843009
功能:比较从 p t r 1 ptr1 ptr1 和 p t r 2 ptr2 ptr2 指针指向的位置开始,向后的 n u m num num 个字节
返回值如下:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
4.2、函数的使用
c复制代码
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n = 0;
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 '%s'.\n", buffer1, buffer2);
return 0;
}