在编程过程中,在大量的情况下需要使用memset()函数对内存进行置零初始化(除了这里说的memset()其实很多函数,比如snprintf()、strncpy()等都可以借用这里谈到的方法),以下三种情况是在工作中经常在这方面碰到的错误,大部分错误是因为疏忽而造成的。
例1

char *buf [FAIP_WITHDOT_MAX_LEN+1];
memset (buf, 0, FAIP_WITHDOT_MAX_LEN + 1);

例2

#define DIGEST_LEN 17
#define DIGEST_MAX 16

char digest [DIGEST_MAX];
memset (digest, 0, DIGEST_LEN);

例3

dll_node_t *p_node = malloc (sizeof (dll_node_t));
if (p_node == 0)
return;
memset (p_node, 0, sizeof (dll_t));

下面示例了如何采用一般化的方法更正上面的三种错误。
例1修订1

char *buf [FAIP_WITHDOT_MAX_LEN+1];
memset (buf, 0, sizeof (char *) * (FAIP_WITHDOT_MAX_LEN + 1));

例2修订1

#define DIGEST_LEN 17
#define DIGEST_MAX 16

char digest [DIGEST_MAX];
memset (digest, 0, DIGEST_MAX);

例3修订1

dll_node_t *p_node = malloc (sizeof (dll_node_t));
if (p_node == 0)
return;
memset (p_node, 0, sizeof (dll_node_t));

需要思考的是,如何在工作中尽可能的避免这类“低级”错误。虽然可以通过采用code review的方式增加错误的检出率,但这种效果并不好。更为好一点的方法是程序员养成一定的编程习惯,比如采用这里将要主张的sizeof()方法就能显著地降低这类错误。下面示例了如何采用sizeof()来更正错误。
例1修订2

char *buf [FAIP_WITHDOT_MAX_LEN+1];
memset (buf, 0, sizeof (buf));

例2修订2

#define DIGEST_LEN 17
#define DIGEST_MAX 16

char digest [DIGEST_MAX];
memset (digest, 0, sizeof (digest));

例3修订2

dll_node_t *p_node = malloc (sizeof (dll_node_t));
if (p_node == 0)
return;
memset (p_node, 0, sizeof (*p_node));

这里所说的采用sizeof()规避错误的方法其背后的思想是什么呢?人的大脑是注定要出错的,如果在大脑中存有处理同一事务的大量规则或根本没有规则,那么往往在处理这一事务时更容易出错。采用memset()函数对内存初始化就属于容易出错的一类事务,因为在指定实际被初始化内存的大小时,一般化的方法是需要根据被初始化内存的上下文来决定传递给memset()函数内存大小的具体值。如果采用sizeof()来获取所需初需化内存的大小并将其固化成编程习惯,那么就不容易出错。

对于前面的第一和第二种错误,只需要将数组当作sizeof()的参数,而不用关心数组在定义时的大小到底是多少。即使因为需要而更改目标数组的大小,sizeof()仍会返回更改后的实际数组的大小,而不需要对memset()函数的调用做任何的手动更改。对于第三种错误,方法是相类似的,只不过要采用sizeof(*xxx)的形式,其中xxx是目标指针变量,比如前面第三个例子中的p_node。

注意到采用sizeof()方法的共性了吗?都是以需要初始化的目标变量作为sizeof()的参数的,而不是以目标变量的类型或是宏作为其参数,这种方式使得写出来的程序更加不容易出错。采用sizeof()方法,对于获取被初始化内存的大小简化为只有两条规则:
1)如果目标变量是一个数组,则采用sizeof(xxx)的格式获取内存大小,其中的xxx是指数组变量名,显然这个数组变量可以是嵌套在另一个数据结构中的。
2)如果目标变量是一个数据结构的指针,则采用sizeof(*xxx)获取内存大小,其中的xxx则是指数据结构指针变量名,而不是数据结构类型。

最后一个问题是,采用sizeof()会降低程序的性能吗?不会!因为sizeof()是在程序编译时由编译器进行计算并最终得出一个数字的,是一个静态的行为而不是运行时行为。

转载于:https://blog.51cto.com/yunli/227130

【编程好习惯】使用sizeof减少内存操作失误相关推荐

  1. C语言嵌入式系统编程修炼之内存操作

    数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力.在嵌入式系统的实际调试中,多借助C语言指针所具 ...

  2. 嵌入式系统编程之内存操作的注意事项

    关注.星标公众号,直达精彩内容 ID:技术让梦想更伟大 整理:李肖遥 在嵌入式系统的编程中,内存操作是我们常用到的,但往往也是易错的地方,怎么避免呢,今天给大家分享一些相关的避坑指南. 数据指针 在嵌 ...

  3. STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)

    1.内存操作 在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜 数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它 ...

  4. c语言中指针往内存写值,C语言编程常见问题解答之指针和内存分配

    指针为C语言编程提供了强大的支持--如果你能正确而灵活地利用指针,你就可以直接切入问题的核心,或者将程序分割成一个个片断.一个很好地利用了指针的程序会非常高效.简洁和精致. 利用指针你可以将数据写入内 ...

  5. C++编码中减少内存缺陷的方法和工具

    2019独角兽企业重金招聘Python工程师标准>>> C++编码中减少内存缺陷的方法和工具 程振林,方金云,唐志敏 (中国科学院计算技术研究所,北京 100080) 摘 要:基于C ...

  6. C#中Marshal 类的内存操作的一般功能概述

    Marshal 类的内存操作的一般功能 Marshal类 提供了一个方法集,这些方法用于分配非托管内存.复制非托管内存块.将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法 ...

  7. Getmemory函数详解--内存操作的理解

    题目:void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemor ...

  8. 【C进阶】之动态内存分配及内存操作函数

    动态内存分配及内存操作函数 1 动态内存分配的介绍 2 malloc和free函数 3 测试代码 4 goto的使用场合,常用于出错处理 5 memset() 6 memcpy() 7 memcmp( ...

  9. 《JAVA并发编程的艺术》之Java内存模型

    <JAVA并发编程的艺术>之Java内存模型 文章目录 <JAVA并发编程的艺术>之Java内存模型 Java内存模型的基础 并发编程模型的两个关键问题 Java内存模型的抽象 ...

  10. c语言常用编程,常用C语言编程的习惯.doc

    常用C语言编程的习惯 编程修养 2011-11-12什么是好的程序员?是不是懂得很多技术细节?还是懂底层编程?还是编程速度比较快?我觉得都不是.对于一些技术细节来说和底层的技术,只要看帮助,查资料就能 ...

最新文章

  1. 理解进化的五座“桥”
  2. 为何 short s1 = 1; 是对的,而 float f=3.4; 是错的?
  3. 在CISCO交换机上配置SSH
  4. cmd 一键获取 所有连接过的wifi 密码
  5. LinkedHashMap的实现原理
  6. 仓库温度湿度控制措施_药品仓库如何保持温湿度均衡?
  7. Maven解决Failed to instantiate SLF4J LoggerFactory报错
  8. 汽车行业要变天?数据告诉你,为什么说合资车企正在走向末路
  9. 小米回应设备被谷歌禁用;苹果中国宣布 2019 款 iPad 降价;Wine 5.0-rc4 发布 | 极客头条...
  10. Git branch 用法
  11. Java实现MongoDB的日期(Date)分组功能
  12. 魔兽世界 MPQ(MoPaQ) 文件相关资料
  13. extremecomponents -- 文档下载依赖使用
  14. 解决ImportError: /lib64/libm.so.6: version `GLIBC_2.23‘ not found (required by /root/anaconda3/lib/pyt
  15. poj 1840(数的hah)
  16. 一杯凉茶 mysql_那一杯凉茶
  17. zoom使用教程_如何使用Zoom在线玩Jackbox游戏
  18. 1星《微信软文营销实战技巧》:标题党,作者没有实战经验
  19. 电容式液晶屏可实现多点触控
  20. c语言几张图片合成视频,一张有料的图片!!!附文件-图片合成器C语言实现算法-站长资讯中心...

热门文章

  1. jQuery的对象访问函数(get,index,size,each)
  2. React组件之间的通信
  3. C++ 类型转换操作与操作符重载 operator type() 与 type operator()
  4. 学在LINUX下编程(转)
  5. 优化CUDA数据传输
  6. 利用卷积进行序列到序列学习
  7. Apache部署多个WordPress网站
  8. Docker客户端连接Docker Daemon的方式
  9. python 中list的操作(循环、切片、增、删、改、查、反转、排序)
  10. swiper控件(回调函数)