透彻分析C/C++中memset函数

透彻分析C/C++中memset函数透彻分析 C C 中 memset 函数 nbsp nbsp 在 C 语言中 经常需要对内存进行操作 里面涉及很多函数 但是 memset 函数的使用有一点需要大家格外注意 这也是我在做项目时遇到过的一个问题 调试了很久才找出来错误 nbsp nbsp 函数原型是 void memset void s intch size tn nbsp nbsp 函数功能是 将 s 所指向的某一块内存中的前 n 个字节的内

透彻分析C/C++中memset函数



    在C语言中,经常需要对内存进行操作,里面涉及很多函数,但是memset函数的使用有一点需要大家格外注意,这也是我在做项目时遇到过的一个问题,调试了很久才找出来错误。


    函数原型是:void *memset(void *s, int ch, size_t n);

    函数功能是:将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针,它是对较大的结构体或数组进行清零操作的一种最快方法


    头文件是:<memory.h>或<string.h>


    这些解释在百度里面随处可见,而这里需要强调的是一些需要引起大家重视的关键点。


    1. 基本应用场合


    memset函数通常用来对一块已经分配地址的内存进行初始化,并且通常初始化为0或者字符’\0’(实际上是一样的)。下面是一些常见例子。


/*===注意:这些例子如果同时运行需要在C++编译环境下===*/ int i = 0; // 例1:对字符数组进行初始化 char buf[10]; memset(buf, '\0', sizeof(char) * 10); // 0或者'\0'是等价的 for (i = 0; i < 10; ++i) { printf("%c", buf[i]); } printf("\n"); // 例2:对字符指针所指区域初始化,必须已经分配内存 char* pBuf = (char *)malloc(sizeof(char) * 10); if (pBuf != NULL) { memset(pBuf, 0, sizeof(char) * 10); // 0或者'\0'是等价的 for (i = 0; i < 10; ++i) { printf("%c", pBuf[i]); } printf("\n"); free(pBuf); pBuf = NULL; } // 例3:对整型数组进行初始化 int iBuf[10]; memset(iBuf, 0, sizeof(int) * 10); for (i = 0; i < 10; ++i) { printf("%d ", iBuf[i]); } printf("\n");

    上面的这些例子已经比较清楚地展示了memset函数的使用,当然,很常见的还有对结构体进行这样的初始化操作,唯一的区别就是sizeof()的对象变成结构体即可,这里大家可以自己尝试。


    2. 需要注意的几点


(1)memset中的第三个参数一定要使用sizeof操作符,因为每个系统下对类型长度的定义可能不一样。


(2)memset中的第一个参数一定要是一个已知的、已经被分配内存的地址,否则会出错。


(3)大家可能比较疑惑,memset的第一个参数已经有了被初始化空间的首地址,为什么还要返回一个void*的指针去指向这个地址呢?这种结构在很多函数库里面比较常见,比如字符串操作函数等,都有类似的现象,这里之所以还要返回这个指针是为了实现链式编程,所谓链式编程,举个例子大家就明白了。


// 例4:链式编程 int i = 0; char cBuf [10]; char cBuf1[10]; // 这里是关键!!! memcpy(cBuf1, memset(cBuf, 'a', sizeof(char) * 10), sizeof(char) * 10); for (i = 0; i < 10; ++i) { printf("%c", cBuf[i]); } printf("\n"); for (i = 0; i < 10; ++i) { printf("%c", cBuf1[i]); } printf("\n");
 
    
从上面这个例子中就可以看出,在memcpy这个函数中,直接使用了memset的返回值,用其来拷贝cBuf1这个字符数组,这样就可以直接连起来写,看起来十分方便。但是这个例子的应用形式却很少,只是为了说明这个问题才这样写的,具体的链式编程应用场合大家可以再仔细研究下,但是链式编程也使得代码变得有些不直观,所以要有所取舍。


(4)最后一点,也是最重要的一点。一定要注意,memset是按照字节对待初始化空间进行初始化的,也就是说,函数里面的第二个参数的那个初值(一般为0)是按照一个一个字节往第一个参数所指区域赋值的,所以,对于单字节数据类型(char)可以初始化为任意支持的值,都没有问题,但是对于非多字节数据类型只能初始化为0,而不能初始化成别的初值,因为对所有字节按任意顺序赋值0的结果都是0,而如果初始化为其他的值,就会一个字节一个字节的进行赋值,从而出现奇怪的结果。比如说,上面的例3之所以没有出错就是因为初始化为0,但是如果初始化为1,那么因为int一般是4个字节,那么相当于将一个int元素初始化成了0000 0001 0000 0001 0000 0001 0000 0001,这样对于一个int元素肯定不是1,而是一个很大的数,结果出乎意料,所以一定要记住这一点,非常重要!!!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233522.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • gis中char是什么字段_gis中字段类型char

    gis中char是什么字段_gis中字段类型char维护一个字符串集合,支持两种操作:I x 向集合中插入一个字符串 x;Q x 询问一个字符串在集合中出现了多少次。共有 N 个操作,输入的字符串总长度不超过 105,字符串仅包含小写英文字母。输入格式第一行包含整数 N,表示操作数。接下来 N 行,每行包含一个操作指令,指令为 I x 或 Q x 中的一种。输出格式对于每个询问指令 Q x,都要输出一个整数作为结果,表示 x 在集合中出现的次数。每个结果占一行。数据范围1≤N≤2∗104输入样例:5I abcQ abcQ ab

    2022年8月8日
    1
  • django详解_java cookie

    django详解_java cookie前言cookie:在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录

    2022年8月7日
    4
  • datatable删除行

    先列出正确的写法,如果你只想马上改错就先复制吧,如果你有时间想学习一下就继续看下面列出可能出错的可能性吧。1.如果只是想删除datatable中的一行,可以用DataRow的delete,但是必须

    2021年12月24日
    34
  • Vue学习之增删改查小案例

    Vue学习之增删改查小案例Vue学习之增删改查小案例

    2022年4月23日
    50
  • Java–Java版本和JDK版本「建议收藏」

    Java–Java版本和JDK版本「建议收藏」对于Java初学者,经常会听到同事,或看到网上Java版本和JDK版本不一的叫法,不明白这两者到底什么关系?其实博主当年初学Java时也有这样的困惑,今天我们就来好好探讨一下,如有不对之处,请加以指正,不喜勿喷,谢谢!Java版本叫法:Java6、Java8、Java11、Java13(当前最新版本Java17)等这一类“JavaX”的Java版本名称同时又会听到,看到JDK版本叫法:JDK1.6、JDK1.8等这种“J…

    2022年9月15日
    0
  • 十款移动APP开发框架

    十款移动APP开发框架  十款移动APP开发框架:1.jquerymobile框架2.bootstrap框架3.ionic框架4.MobileAngularUI框架5.IntelXDK框架6.AppceleratorTitanium框架7.SenchaTouch框架8.KendoUI框架9.PhoneGap框架10.mui框架  1.jquerymobile框架  jQue…

    2022年5月31日
    375

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号