额外知识点
第一个
假设c为int类型,(char)c之后,之后如果还用变量c的话,c依然为int类型。()强制转换操作符并不会永久改变原本的变量类型。
第二个
\0在打印时不会显示出来
第三个
void *能接收任意类型指针,除了被const修饰的指针类型。 我们要接受被const修饰的指针,就要用const void* 去接受。
memcpy和memmove
memcpy
其格式为
其作用是将从source往后的num个字节拷贝到destination上。(从前往后拷贝)
memcpy相比于strcpy
strcpy只适用于字符串,并且遇到\0就自动结束拷贝
memcpy 对于任何数据类型都能拷贝,所以用void*接收,并且遇到\0不会结束,它只在拷贝完num的字节后结束。
如果destination和source中有重叠的内存,那么就不能用memcpy,否则会发生错误。这时候我们要用到memmove。
有人在vs2022用memcpy对有重叠内存的参数进行拷贝,但是正常结果,这并不代表memcpy本身有能对重叠内存的参数进行拷贝的功能,而是vs2022使memcpy能实现该功能,在其他编译器就不一定了。
所以如果发生这种情况,我们就用memmove,不能用memcpy,即使它在编译器的帮助下也能实现。
memcpy的模拟实现
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
在这我们还知道,对dst 强制类型转换为char*后,并没改变dst的本质void*类型,其本质依然为void*类型,之后如果要用还是要强制转换才能用。
memmove
其格式和memcpy一模一样
其实可以理解memmove为高配的memcpy,当其不重叠时,可以实现,当其重叠时依然可以实现。 而memcpy只能实现不重叠的,重叠的不能实现。 更加高级。
当重叠时,如果依旧拷贝,并且结果依然为正确,那就必须遵循:
当source在dest左边时,向左复制(从后往前复制)。如果source在dest右边,向右移动(从前往后复制)。
所以模拟memmove的代码为
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
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);
}
memset
memset是从ptr地址开始,将每个字节的值变为value值,改变num个字节。
在使用时,由于其改变是改变一个字节,如果在对整形做改变,因为整形为四个字节,所以起不到很好的效果,一般我们都是对字符数组做改变。 (常量字符串不可修改,所以不能当作参数被修改,类型带const,不能被void*接收)
因为是改变一个字节,且一般对字符数组做改变。所以value使用时一般为字符 。
下图是使用时的一个经典例子,一般使用memset都是对字符数组进行改变,使其等于的值一般都为字符。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "hello world";
memset (str,'x',6);
printf(str);
return 0;
}
memcmp
跟strncmp有点像,只不过一个比字符(只能作用于字符串),一个比字节(任意数据都可以)。 其作用原理本质几乎差不多,就从第一个字节大小比较,如果相等比较下一个字节大小。第一个大于第二个返回大于0的整数,相反则返回小于0,相等则返回0.
下面举个例子
#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;
}
总结
这就是我们的内存函数 ,其头文件都为#include<string.h>.到这里,我们就讲了四个内存函数,都是以字节为单位去作用。
之后我们将给大家介绍数据在内存中的存储,谢谢大家!