【今日问题】变量未初始化引起的崩溃

昨天写的今日问题,有小伙伴给我反馈,觉得挺有用,小编今天继续给小伙伴们总结遇到的常见问题

一、初学者经常由于没有养成良好的编程习惯,未初始化变量会引起那些问题

使用未初始化的变量是常见的程序错误,通常也是难以发现的错误。虽然许多编译器都至少会提醒不要使用未初始化变量,但是编译器并未被要求去检测未初始化变量的使用。而且,没有一个编译器能检测出所有未初始化变量的使用。

现象列举:

1、引起程序运行时突然崩溃

  这种结果已近是相当好了,至少你可以发现程序崩溃的位置,及时的修正问题

2、程序运行成功但是结果错了,这种还是比较好查的分析错误原因费点时间

3、程序在不同的机器上运行的结果不一致查找问题那就难上加难了

原因分析:

未初始化的变量事实上都有一个值。编译器把该变量放到内存中的某个位置,而把这个位置的无论哪个位模式当做是变量初始的状态。当被解释成整型值时,任何为模式都是合法的值——虽然我这个值不可能是程序员想要的,因为这个值合法,所以使用它不可能会导致程序崩溃。可能的结果是导致程序错误执行或者错误计算。

建议:

建议每一个内置类型的对象都要初始化。虽然这样做并不总是必须的,但是会更加容易和安全,除非你确定忽略初始化是不会带来风险。

二、初学者误认为宏定义函数和普通函数一致

函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b))

普通函数 : MAX(a,b) { return a>b?a:b;}

两者区别:

1、函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以传参时要格外小心。

2、调用真正函数的代码和调用函数式宏定义的代码编译生成的指令不同。如果MAX是个普通函数,那么它的函数体return a > b ? a : b; 要编译生成指令,代码中出现的每次调用也要编译生成传参指令和call指令。而如果MAX是个函数式宏定义,这个宏定义本身倒不必编译生成指令,但是代码中出现的每次调用编译生成的指令都相当于一个函数体,而不是简单的几条传参指令和call指令。所以,使用函数式宏定义编译生成的目标文件会比较大。

3、函数式宏定义要注意格式,尤其是括号。

  如果上面的函数式宏定义写成 #define MAX(a, b) (a>b?a:b),省去内层括号,a=1+x, b=2+y;则宏展开就成了1+x>2+y?1+x:2+y ,运算的优先级就错了。同样道理,这个宏定义的外层括号也是不能省的。若函数中是宏替换为 ++MAX(a,b),则宏展开就成了 ++(a)>(b)?(a):(b),运算优先级也是错了。

4、若函数参数为表达式,则普通函数的调用与函数式宏定义的替换过程是不一样的。

  普通函数调用时先求实参表达式的值再传给形参,例如MAX(++a, ++b),如果MAX是普通函数,a和b只增加一次。但如果MAX函数式宏定义,则要展开成k = ((++a)>(++b)?(++a):(++b)),a和b就不一定是增加一次还是两次了。所以若参数是表达式,替换函数式宏定义时一定要仔细看好。

总结:

尽管函数式宏定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现。

如果还觉得回答不够彻底就直接加群问小编或者在公众号直接留言。有想让小编总结的话题,都可以直接留言

课后小作业:

#define f(a, b, x)  a*x+b

printf("%d, %dn", f(3,2,1), f(6, 5, f(3, 2, 1)));

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-06-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青枫的专栏

java基础学习_面向对象(下)02_day09总结

============================================================================= ==...

542
来自专栏everhad

札记:Java异常处理

异常概述 程序在运行中总会面临一些“意外”情况,良好的代码需要对它们进行预防和处理。大致来说,这些意外情况分三类: 交互输入 用户以非预期的方式使用程序,比如...

2008
来自专栏老九学堂

原来C语言和其他高级语言的最大的区别是这个...

我们需要知道——变量,其实是内存地址的一个抽像名字罢了。在静态编译的程序中,所有的变量名都会在编译时被转成内存地址。机器是不知道我们取的名字的,只知道地址。

913
来自专栏菜鸟致敬

一分钟带你读懂Python中的三类特殊方法

在Python中有着三类特殊方法:静态方法、类方法以及抽象方法。今天我们来谈谈其中的这三类特殊方法。

452
来自专栏Python专栏

写了这么多年的python,tuple竟然是可变的?

1072
来自专栏编程坑太多

python中yield\\send好处

703
来自专栏极客猴

Python 正则表达式

我们能够使用 urllib 向网页请求并获取其网页数据。但是抓取信息数据量比较大,我们可能需要其中一小部分数据。对付刚才的难题,就需要正则表达式出马了。正则表达...

752
来自专栏IT可乐

Java 字符编码与解码

1、字符编码的发展历程 ①、ASCII 码   因为计算机只认识数字,所以我们在计算机里面的一切数据都是以数字来表示,因为英文字符有限,所以规定使用的字节的最...

21110
来自专栏一英里广度一英寸深度的学习

线性排序算法-堆排序 (2)

在学数据结构的时候,链表、堆栈、树三种数据结构印象最深刻。当时理解有误区,堆栈被当成一种结构,可能因为堆栈有同样的特性——只关心堆顶或栈顶的元素。

803
来自专栏JetpropelledSnake

Python入门之面向对象编程(一)面向对象概念及优点

本文分为如下几个部分 首先说明面向对象是什么,然后结合实际例子说明面向对象的如下几个优点 方便函数管理 数据封装 对象操作 最后总结一下面向对象的好处 概念...

3547

扫码关注云+社区