前言:
文接上章,在上章为大家讲解了内存复制------memcpy函数和内存移动------memmove函数,也实现了模拟实现,比较了他们的区别。复习一下吧:
memcpy
可以对空间不重叠的情况进行任意类型的元素拷贝;memmove
可以对空间重叠的情况进行任意类型的元素拷贝;
这种理解方式是复合C语言规定的理解,但是在VS2019中不管是memmove
还是memcpy
都是能够实现对重叠空间的数据拷贝。
在本章为大家讲解剩下的函数
一·内存查找字符---memchr
1.1函数原型:
cs
void* memchr(const void* ptr, int value, size_t num);
- ptr:指向要搜索的内存区域的指针。
- value:要查找的字符(以无符号字符形式表示)。
num
:要搜索的字节数量。
功能 :在ptr
指向的内存前n
字节中搜索value
的第一次出现
memchr
函数有三个参数------指向查找空间的指针ptr
、要查找的元素对应的整型值value
、以及要查找的字节数num
。
在函数介绍中对于该函数的描述是在指针ptr
指向的内存块的第一个num
字节中搜索第一个value
(解释为无符号字符类型),并返回指向他的指针。
其次是函数的底层逻辑------将value
解释为无符号字符类型。这里要注意的是什么是无符号字符类型。
最后是函数的返回值------返回指向value的指针。这个我们并不陌生了,在前面实现memcpy
的时候我们就有介绍过对于void*
类型的函数在函数结束时,需要给函数返回一个地址,这里就不再继续展开。
1.2函数的使用
cs
#include <stdio.h>
#include <string.h>
int main() {
const char *str = "http://www.example.com ";
char ch = '.';
void *ret = memchr(str, ch, strlen(str));
if (ret) {
printf("Character '%c' found at position %ld\n", ch, (long)(ret - str));
} else {
printf("Character '%c' not found\n", ch);
}
return 0;
}
只要在查找的过程中找到了value
就不会继续往后查找,而是直接返回该value
的地址。
注意事项
memchr
函数将c
视为无符号字符,因此在比较时可能受到数据类型的影响。例如,如果c
是一个负数(如-1
),它会被转换为一个较大的无符号数(如0xFFFFFFFF
),从而导致查找范围扩大。- 在某些情况下,
memchr
可能会在非预期的内存区域中找到匹配值,例如在整型数组中,这可能与内存存储格式有关(如小端模式或大端模式)。
这函数涉及数据储存,需要了解电脑储存数据的方式,比较复杂。
无需过多理解
二·内存设置---memset
内存设置函数我们可以理解为是一个用来修改内存块的函数
2.1函数原型:
cs
void* memset(void* ptr, int value, size_t n);
功能 :将ptr
指向的内存区域的前n
个字节都设置为value
值。
从函数的介绍中我们可以看到,该函数有3个参数------指向需要填充的内存块的指针,需要填充的值,以及需要填充的字节数。memset
的底层逻辑是逐个字节进行设置
2.2函数的使用
cs
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello csdn";
memset(arr+2, 'x', 5);
printf("%s", arr);
return 0;
}

memset可以修改字符数组。
这里提出一个疑问,memset函数可以用来修改整型数组嘛 ?
cs
#include <stdio.h>
#include <string.h>
int main()
{
//char arr[] = "hello csdn";
//memset(arr+2, 'x', 5);
//printf("%s\n", arr);
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memset(arr1, 1, 10);
for (int i = 0;i < 10;i++)
{
printf("%d", arr1[i]);
}
return 0;
}

很显然答案不是我们想要的,这是为什莫呢?
大家不要忘记memset函数是逐个字节修改的,而整形是有四个字节组成的,所以这里的第一个错误是字节个数不对,应该是40个,而不是10个。
那修改完后是否就正确了呢?

啊哦,还是错误的呢,这又是为什莫?
思考一下,还是字节的问题,一个整形有四个字节,修改完后,为01 01 01 01,显然是不对的。
但是如果要设置全0的话,是可以的。

三·内存比较---memcmp
内存比较函数与strcmp很相似都是通过逐字节来进行内存比较的
3.1函数原型:
cs
int memcmp(const void* ptr1, const void* ptr2, size_t n);
返回值:
-
0:内存内容完全相同
-
<0:第一个不同字节在ptr1中的值更小
-
0:第一个不同字节在ptr1中的值更大
3.2 函数的使用
memcmp
的使用方式与strncmp
是一致的,都是给函数传入三个参数------指向需要进行比较的两个内存空间的指针以及需要比较的字节数,但是两个函数的底层实现上是有区别的,strncmp
在进行比较时会以'\0'
作为结束标志,但是memcmp
在进行比较时,则不会受到'\0'的影响。
整形类型的比较:
cs
#include <stdio.h>
#include <string.h>
int main()
{
//0x 00 00 00 01
int arr1[] = { 1,2,3,4,5 }; //0x 00 00 00 05 ,
//倒着储存。
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 01 33 23 12
int arr2[] = { 1,2,3,4,0x12233301 };
//0x 12 23 33 01
int r = memcmp(arr1, arr2, 17);
printf("%d\n", r);
return 0;
}

字符串类型的比较:
cs
char arr1[] = "abc\0defg";
char arr2[] = "abc\0zefg";
printf("%d\n", strncmp(arr1, arr2, 5));
printf("%d\n", memcmp(arr1, arr2, 5));

可以看到,在给两个函数传入同样的参数时,函数的返回值上是有区别的,strncmp
在比较到第3个字节时,因为遇到了'\0'
就结束了后续的比较,但是memcmp
在遇到了'\0'后继续往后进行了比较,并arr1的第四个字节的ASCII码值是大于arr2的ASCII码值,所以返回值小于0 。
还可以结构体的比较,浮点的比较等等------
总结:
在今天的内容中我们介绍了一系列的内存函数:
- 内存查找字符------
memchr
- 内存设置函数------
memset
- 内存比较函数------
memcmp
要注意 memchr与memset函数都是逐字节的进行查找或者修改,因此在具体的使用过程中如果使用不当可能就会造成一些错误。
今天的内容到这里就全部结束啦!!如果大家喜欢博主的内容,可以点赞、收藏加评论支持一下博主。
最后感谢各位朋友的支持,咱们下一章再见!!!
下章为大家讲解数据在内存中的储存