在文章嵌入式Linux开发《C语言专题(五:(3)函数之字符串函数1)》嵌入式Linux开发《C语言专题(五:(3)实用的字符串函数2)》和嵌入式Linux开发《C语言专题(五:(3)实用的字符串函数3)》中对C语言中字符串函数做了详细介绍,这篇文章将介绍部分操作内存的函数。这些内存函数在实际的研发和面试中也有很大的用处。
内存操作函数有memcpy、memmove、memset、 memcmp 、memchr 、memrchr 、 malloc、calloc、 free、 realloc 等,大多数以mem开头。
(1)memcpy:从内存区域src的位置复制n字节到内存区域dest位置
函数名:memcpy
函数原型:void *memcpy(void *dest, const void *src, size_t n);
函数参数:dest:目标内存区
src:源内存区
n:复制的数据字节个数
头文件: #include <string.h>
功能:从内存区域src的位置复制n字节到内存区域dest位置
返回值:返回dest指针
说明:要确保src内存区域位置不要与内存区域dest重合,否则会出现意想不到的结果。
此函数并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的
使用带来了很大的灵活性,可以对任何数据类型进行复制。dest 指针要分配足够
的空间,也即大于等于 num 字节的空间。如果没有分配空间,可能会修改dest相邻
后面内存的值。
代码演示:
#include <stdio.h>//一定要加上操作头文件 #include <string.h> //演示memcpy内存复制操作 int main(int argc, char** argv) { char str = "hello world"; //第一种:str和dest内存空间不重合,且dest空间足够 //运行结果:显示dest中的内容: hello world char dest[20] = {0}; memcpy(dest, str, strlen(str)); printf("显示dest中的内容: %s \n", dest); / 第二种:str和dest内存空间不重合,且dest空间不足 //虽然数据也能复制过去,但是可能会修改与dest相邻后面内存的值 //运行结果:显示dest中的内容: hello world char dest[2] = {0}; memcpy(dest, str, strlen(str)); printf("显示dest中的内容: %s \n", dest); / / 第三种:str和str+2内存空间重合 //运行结果:Segmentation fault (core dumped) memcpy(str+2, str, strlen(str)); //hehello wor printf("显示str中的内容: %s \n", str); */ return 0; }
复制代码(2)memmove:从内存区域src的位置复制n字节到内存区域dest位置
函数名:memmove
函数原型:void *memmove(void *dest, const void *src, size_t n);
函数参数:dest:目标内存区
src:源内存区
n:复制的数据字节个数
头文件: #include <string.h>
功能:从内存区域src的位置复制n字节到内存区域dest位置
返回值:返回dest指针
说明:src内存区域位置与内存区域dest可以覆盖。具体复制的方法是:先将src开始的n个字
节的内容复制到不会覆盖src和dest位置的临时数组中,然后将临时数组中的内容再
复制到dest中。所以如果src和dest有重叠时,要用memmove来复制,保证不会出
错。
代码演示:
#include <stdio.h>//一定要加上操作头文件 #include <string.h> //演示memmove内存复制操作 int main(int argc, char** argv) { /* //第一种:str和dest内存空间不重合,且dest空间足够 //运行结果:显示dest中的内容: hello world char *str = "hello world"; char dest[20] = {0}; memmove(dest, str, strlen(str)); printf("显示dest中的内容: %s \n", dest); */ /* //第二种:str和dest内存空间不重合,且dest空间不足 //虽然数据也能复制过去,但是可能会修改与dest相邻后面空间的值 //运行结果:显示dest中的内容: hello world char *str = "hello world"; char dest[2] = {0}; memmove(dest, str, strlen(str)); printf("显示dest中的内容: %s \n", dest); */ //第三种:str和str+2内存空间重合,用memmove复制之后,str中的内容没有受影响 //用memcpy后有影响 //运行结果:显示str中的内容: hello world //显示dest中的内容: hello world char str[20] = "hello world"; char dest = NULL; dest = str + 2; memmove(dest, str, sizeof(str)); printf("显示str中的内容: %s \n", str); printf("显示dest中的内容: %s \n", dest); / //显示str中的内容: hehellllwowod //显示dest中的内容: hellllwowod memcpy(dest, str, sizeof(str)); printf("显示str中的内容: %s \n", str); printf("显示dest中的内容: %s \n", dest); */ //使程序暂时停止,防止出现* stack smashing detected *: ./memory terminated Aborted (core dumped) pause(); return 0; }
复制代码(3)memset:用常量c来填充内存区域s开始的n个字节
函数名:memset
函数原型:void *memset(void *s, int c, size_t n);
函数参数:s:内存区域的起始地址
c:要填充的常量
n:填充的字节数
头文件: #include <string.h>
功能:用常量c来填充内存区域s开始的n个字节
返回值:返回内存区域s的指针
说明:可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。因为是按
字节进行赋值,所以一定要注意给非字符数组赋值时的情况。
代码演示:
与它相关常用的函数是bzero:设置从s位置开始的n个字节的值为0也即\0
函数名:bzero
函数原型: void bzero(void *s, size_t n);
函数参数:s:起始地址
n:填充的字节数
头文件:#include <string.h>
功能:设置从s位置开始的n个字节的值为0也即\0
返回值:无
说明:常常用在定义数组后,对数组进行初始化时的操作。
代码演示:
#include <stdio.h>//一定要加上操作头文件 #include <string.h> //演示memset给字符数组和非字符数组内存操作 int main(int argc, char** argv) { /* 第一种:给字符数组赋值 char str[2] = {'1','1'}; int i = 0; printf("memset之前"); for(i = 0; i < sizeof(str); i++) { printf("str[%d]的内容: %c \n", i, str[i]); } memset(str, 0, sizeof(str)); //结果为0 //memset(str, 1, sizeof(str)); //结果为1 //bzero(str, sizeof(str));//结果为0 printf("memset之后"); for(i = 0; i < sizeof(str); i++) { printf("str[%d]的内容: %d \n", i, str[i]); } / //第一种:给非字符数组赋值 int str[2] = {1,1}; int i = 0; / 运行结果: memset之前str[0]的内容: 1 str[1]的内容: 1 memset之后str[0]的内容: 16843009 str[1]的内容: 16843009 */ //结果不是1而是16843009 对应二进制是:0000 0001 0000 0001 0000 0001 0000 0001 //也就是说每一个字节的值是1,但是整型是由4个字节组成的,所以最终的赋值结果 //不是我们想要的1, printf("memset之前"); for(i = 0; i < sizeof(str) / sizeof(int); i++) { printf("str[%d]的内容: %d \n", i, str[i]); } memset(str, 1, sizeof(str)); //bzero(str, sizeof(str));//结果依然为0 printf("memset之后"); for(i = 0; i < sizeof(str) / sizeof(int); i++) { printf("str[%d]的内容: %d \n", i, str[i]); } return 0; }
复制代码(4)memcmp:以无符号字符逐个比较内存区域s1和s2前n个字节字符的大小
函数名:memcmp
函数原型:int memcmp(const void *s1, const void *s2, size_t n);
函数参数:s1:第一个内存区域要比较的地址
s2:第二个内存区域要比较的地址
n:比较的字节个数
头文件:#include <string.h>
功能:以无符号字符逐个比较内存区域s1和s2前n个字节字符的大小
返回值:如果s1小于s2则比较的结果小于0,如果s1大于s2则比较的结果大于0,如果
s1等于s2则比较的结果等于0,
说明:该函数是按字节比较的,可以将比较的结果与0比较来判断大小
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <string.h>
//演示memcmp内存操作
int main(int argc, char** argv)
{
char *src = "aa";
char *dest = "ab";
int n = memcmp(src, dest, strlen(src));
//运行结果:aa小于ab
if (n == 0)
{
printf("aa等于ab \n");
}
else if(n > 0)
{
printf("较aa大于ab \n");
}
else
{
printf("aa小于ab \n");
}
return 0;
}
//一定要加上操作头文件
#include <string.h>
//演示memcmp内存操作
int main(int argc, char** argv)
{
char *src = "aa";
char *dest = "ab";
int n = memcmp(src, dest, strlen(src));
//运行结果:aa小于ab
if (n == 0)
{
printf("aa等于ab \n");
}
else if(n > 0)
{
printf("较aa大于ab \n");
}
else
{
printf("aa小于ab \n");
}
return 0;
}
(5)memchr:查找s开头的前n个字节是否有匹配的字符c
函数名:memchr
函数原型:void *memchr(const void *s, int c, size_t n);
函数参数:s:内存区域的起始地址s
c:要查找的字符
n:要查找的字节个数
头文件:#include <string.h>
功能:查找s开头的前n个字节是否有匹配的字符c
返回值:当第一次遇到字符ch时停止查找,成功返回指向匹配字符的地址 失败返回NULL
说明:c和s都作为无符号字符进行查找,注意只要找到第一个匹配就立马返回。常常用在查
找第一次出现某个字符的地方。查找的字符区分大小写
代码演示:
#include <stdio.h>//一定要加上操作头文件 #include <string.h> //演示memchr内存操作 int main(int argc, char** argv) { char *str = "hello world"; //str的地址为:0x8048570 //查找str中第一个字母l的位置:0x8048572 //刚好地址相差2个字节,确实是找到第一个l的位置 printf("str的地址为:%p \n", str); printf("查找str中第一个字母l的位置:%p \n", memchr(str, 'l', strlen(str))); return 0; }
复制代码(6)memrchr:查找s开头的后n个字节是否有匹配的字符c
函数名:memrchr
函数原型:void *memrchr(const void *s, int c, size_t n);
函数参数:s:内存区域的起始地址s
c:要查找的字符
n:要查找的字节个数
头文件:#include <string.h>
功能:查找s开头的后n个字节是否有匹配的字符c
返回值:当第一次遇到字符ch时停止查找,成功返回指向匹配字符的地址 失败返回NULL
说明:c和s都作为无符号字符进行查找,注意只要找到第一个匹配就立马返回。常常用在
查找最后一次出现某个字符的地方。
代码演示:
#include <stdio.h>//一定要加上操作头文件 #include <string.h> //演示memrchr内存操作 int main(int argc, char** argv) { char *str = "hello world"; // str的地址为:0x8048590 // 查找str中最后一个字母l的位置:0x8048599 //刚好地址相差9个字节,确实是找到最后一个l的位置 printf("str的地址为:%p \n", str); printf("查找str中最后一个字母l的位置:%p \n", memrchr(str, 'l', strlen(str))); return 0; }
复制代码