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

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

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

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

现象列举:

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的split的小问题

2696
来自专栏java学习

面试题34(关于接口的理解?)

对接口的描述正确的是? A 一个类可以实现多个接口 B 接口可以有非静态的成员变量 C 接口可以实现方法 D 实现接口的任何类,都需要实现接口的方法 考点:考察...

3126
来自专栏维C果糖

史上最简单的 MySQL 教程(十一)「列类型 之 字符串型」

所谓的列类型,其实就是指数据类型,即对数据进行统一的分类,从系统的角度出发是为了能够使用统一的方式进行管理,更好的利用有限的空间。

40210
来自专栏决胜机器学习

PHP数据结构(十七) ——内部排序综述

PHP数据结构(十七)——内部排序综述 (原创内容,转载请注明来源,谢谢) 一、稳定性 假设Ki=Kj(1<=i,j<=n,i!=j),且排在序列前的序列中R...

32012
来自专栏Vamei实验室

Python基础10 反过头来看看

从最初的“Hello World”,走到面向对象。该回过头来看看,教程中是否遗漏了什么。 我们之前提到一句话,"Everything is Object". 那...

1699
来自专栏Java学习网

Java实现的手工做乘法方法,给出二个字符串数字,返回相乘结果

给定两个字符串数字,返回两数字相乘的结果字符串;如:String a="200",String b="10",要求返回"2000"。 问题分析: 解决这个问题的...

2969
来自专栏Hongten

对"for循环中尽量减少对变量的重复计算"提出质疑

===========================================================

481
来自专栏王小雷

Python之NumPy实践之数组和矢量计算

Python之NumPy实践之数组和矢量计算 1. NumPy(Numerical Python)是高性能科学技术和数据分析的基础包。 2. NumPy的nda...

1988
来自专栏我的技术专栏

C++编译期多态与运行期多态

1014
来自专栏King_3的技术专栏

leetcode-78-子集(用bfs解决)

vector<vector<int>> subsets(vector<int>& nums)

601

扫描关注云+社区