forum.jpg

在文章嵌入式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;
  • }
  • 复制代码
    forum.jpg

    (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;        
    }
    forum.jpg

    (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;
  • }
  • 复制代码
    forum.jpg