void *memset(void *s, int ch, size_t n);
作用:将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作。
不知道有没有像我一样把memset当作万能的初始化工具,例如:
int arr[n];
memset(arr,1,n*sizeof(int));
这样得到的arr数组一定不是全0,而是16843009,下面解释原因。
首先,变量类型的本质只是标志从某一内存地址开始读取的位数,强制转换就是改变读取位数的大小。

下面来看memset的实现:(代码来自《C标准库》P398)

void *(memset) (void *s,int c,size_t n)
{
const unsigned char uc = c;
unsigned char *su;
for(su = s;0 < n;++su,--n)
*su = uc;
return s;
}

第3行把int类型的c转换成unsigned char类型,意味着截去c的高24位,只保留低8位。第4行把s当作unsigned char*类型,也就是说su中的每一个元素按8位计算。
现在来看看文章开头的那个代码会做什么。
c的二进制 : 00000000000000000000000000000001(32位)
1、c转换为unsigned char 后:00000001(8位)
2、将指针su(unsigned char类型)的每一元素(8位)赋值为00000001,循环4n次。
3、memset()结束后,arr的每个元素按照int类型读取,读出来的就是1000000010000000100000001,十进制就是16843009。
不过如果是memset(arr,0,n*sizeof(int));的话可以使用,因为32位都是0

再来说memset()的效率问题。使用memset函数与将上面的函数代码写在自己的程序里是不一样的,C标准库中的memset对Cache的利用做了优化,具体的在《C专家编程》151页有解释(其实是我没看懂),这里给出测试:

#include <string.h>
#define MAXSIZE 100000 int main()
{
char arr[MAXSIZE];
for(int i=0;i<10000;i++)
{
memset(arr,'0',sizeof(arr));
// for(int j=0;j<MAXSIZE;j++)
// arr[0] = '0';
}
return 0;
}

程序里的注释部分与memset行分别使用,结果是使用memset的程序运行时间大约为0.1s,而用for循环的程序要3s多。
综上:memset()可以用在字符数组的初始化以及类似于memset(arr,0,n*sizeof(int));的情况,效率比手动赋值要高的多。

 

C++ - memset的效率和源码分析的更多相关文章

  1. Android Debuggerd 简要介绍和源码分析(转载)

    转载: http://dylangao.com/2014/05/16/android-debuggerd-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%92%8C%E ...

  2. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...

  3. Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...

  4. Kubernetes Job Controller 原理和源码分析(一)

    概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...

  5. Kubernetes Job Controller 原理和源码分析(二)

    概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...

  6. Kubernetes Job Controller 原理和源码分析(三)

    概述Job controller 的启动processNextWorkItem()核心调谐逻辑入口 - syncJob()Pod 数量管理 - manageJob()小结 概述 源码版本:kubern ...

  7. jQuery静态方法globalEval使用和源码分析

    Eval函数大家都很熟悉,但是globalEval方法却很少使用,大多数参考手册也没有相关api,下面就对其用法和源码相应介绍: jQuery.globalEval()函数用于全局性地执行一段Java ...

  8. java集合框架04——LinkedList和源码分析

    上一章学习了ArrayList,并分析了其源码,这一章我们将对LinkedList的具体实现进行详细的学习.依然遵循上一章的步骤,先对LinkedList有个整体的认识,然后学习它的源码,深入剖析Li ...

  9. Java1.7 HashMap 实现原理和源码分析

    HashMap 源码分析是面试中常考的一项,下面一篇文章讲得很好,特地转载过来. 本文转自:https://www.cnblogs.com/chengxiao/p/6059914.html 参考博客: ...

随机推荐

  1. vim 将文件从dos格式转换到unix格式

    dos格式文件传输到unix系统时,会在每行的结尾多一个^M(/r),当然也有可能看不到.但是在vim的时候,会在下面显示此文件的格式,比如 "dos.txt" [dos] 120 ...

  2. 【Python】实现将testlink上的用例指定格式保存至Excel,用于修改上传

    背景 前一篇博客记录的可以上传用例到testlink指定用例集的脚本,内部分享给了之后,同事希望能将testlink上原有的用例下载下来,用于下次修改上传,所有有了本文脚本. 具体实现 获取用例信息 ...

  3. Java IO流-字节流

    2017-11-05 17:48:17 Java中的IO流按数据类型分类分为两种,一是字节流,二是字符流.字符流的出现是为了简化文本数据的读入和写出操作. 如果操作的文件是文本文件,那么使用字符流会大 ...

  4. 理解 Git 的基本概念 ( Merging Collaborating Rebasing)

    合并 Merging 在分支上开发新功能后,如何把新功能加入到主分支,让其它人得到你的修改呢?你需要使用命令 git merge 或 git pull. 这两个命令的语法如下: git merge [ ...

  5. 本地Run Page时报检测到意外的 URL 参数,它将被忽略。

    经查,是因为我RUN的时候 Target URL -- http://MY-PC:8988/OA_HTML/runregion.jsp 将MY-PC更改为本地IP即可. 设置方法 Tools - Em ...

  6. 浅谈jsonp

    要谈jsonp,首先要弄明白jsonp是什么,它是用来干嘛的.jsonp其实就是我们常用的script标签,用来解决跨域的,只不过这个标签是动态创建的,为啥要动态创建涅. 举个小栗子: 假如我们远程文 ...

  7. Java中如何读写cookie (二)

    Java中删除cookie Cookie[]   cookies=request.getCookies();       //cookies不为空,则清除       if(cookies!=null ...

  8. spring boot与spring mvc的区别

    Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等.但他们的基础都是Spring 的 ioc和 aop ioc 提供了依赖注入的容器 aop ,解决了面向横切面 ...

  9. hdu 6158 The Designer( 反演圆)

    The Designer Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  10. jacoco生成覆盖率

    要统计自动化的覆盖率,所以临时看了下jacoco,记录下过程.后续用的时候方便查看. 1.build.gradle中修改 apply plugin: 'jacoco' android { buildT ...