39.NULL和临时变量和顺序结构

来源:互联网 发布:新西兰 购物 知乎 编辑:程序博客网 时间:2024/06/01 18:39

39.1.C语言中的NULL
(1)从指针角度理解NULL的本质;int_*p;(若p是1个函数内的局部变量,则p的值是随机的,即p是1个野指针);int_*p=NULL;(若p是1个局部变量,则p的值是(void_*)0,实际就是0,意思是指针p指向内存的0地址处,则p不是野指针)(见图1)。
(2)在大部分的CPU中,内存的0地址处是操作系统严密管控区域,所以应用程序不能随便访问;野指针指向了该区域可以保证野指针不会造成误伤,若程序无意识的解引用指向0地址处的野指针则会触发段错误,则可以提示你帮助你找到程序中的错误。
(3)NULL的第1个作用就是让野指针指向0地址处安全;NULL的第2个作用就是作为1个特殊标记在标准的指针使用步骤起作用(见图2)。
(4)’\0’(转义字符,对应的ASCII编码值是0);’0’(1个字符,对应的ASCII编码值是48);0(1个数字,就是数字0);NULL(1个表达式,强制类型转换为void_*类型的0)。
(5)’\0’用法是C语言字符串的结尾标志,用来比较字符串中的字符以判断字符串有没有到头;’0’是字符0,对应0字符的ASCII编码,用来获取0的ASCII码值;0是数字,用来比较某个int类型的数字是否等于0;NULL是1个表达式,用来比较指针是否是1个野指针。


39.2.运算中的临时匿名变量
(1)C语言-高级语言,汇编语言-低级语言;低级语言即汇编语言和机器操作相对应,汇编语言只是CPU的机器码的助记符,使用汇编语言编程必须拥有机器的思维,因为不同的CPU设计时指令集差异很大,因此针对不同的CPU进行汇编编程的差异很大;高级语言(C语言)对低级语言进行了封装(C语言的编译器完成封装),给程序员提供了靠近人类思维的某些语法特征,人类不用过于考虑机器原理,而可以按照自己的逻辑原理来编程,譬如数组+结构体+指针等;更高级的语言如java或C#等只是更加强化了C语言提供的人性化的操作界面语法,在易用性上和安全性上进行了提升。
(2)高级语言中有些元素是机器中没有的;高级语言在运算中允许我们进行大跨度的运算,即低级语言中需要好几步才能完成的某个运算,在高级语言中只要1步即可完成;譬如C语言中某个变量i要加1,在C中只需要i++即可,实际上翻译到汇编阶段需要3步才能完成;第1步从内存中读取i到寄存器,第2步对寄存器中的i进行加1,第3步将加1后的i写回内存中的i。
(3)使用临时变量来理解强制类型转换;譬如float_a=12.34;int_b=(int)a;(int)a强制类型转换并赋值在底层实际分了4个步骤;第1步先在内存中构建1个int类型的临时变量x,第2步将a整数部分赋值给x,第3步将x赋值给b,第4步销毁x;最后结果表明a还是float而且值保持不变,b是a的整数部分。
(4)使用临时变量来理解不同数据类型之间的运算;譬如int_b=10;float_a;a=b/3;第1步先算b/3,第2步在内存中构建1个float类型的临时变量x并将第1步的结果强制类型转换为float类型然后赋值给临时变量x,第3步将第2步生成的临时变量的值赋值给a,第4步销毁临时变量;最后结果表明b还是int而且值保持不变,a是b除以3后并强制类型转换成float的值。


39.3.顺序结构
(1)最浅显的顺序结构即常用的3种程序结构中的1个;代码执行的时候若没有遇到判断跳转或者循环,默认是顺序执行的,其执行完上1句则开始执行下1句;顺序结构说明CPU的工作状态就是以时间轴来顺序执行所有的代码语句直到停机。
(2)选择和循环结构内部的顺序结构;譬如if(){}在{}内部是if的代码段,在该if的代码段内部还是按照顺序结构来执行的;switch case内部也是按照顺序结构执行的;while和for内部也是按照顺序结构来执行的。
(3)编译过程中的顺序结构;1个C程序由多个.c文件组成,编译的时候多个.c文件是独立分开编译的,每个c文件编译的时候,编译器是按照从前到后的顺序逐行进行编译的;编译器编程时的顺序编译会导致函数/变量必须先定义/声明才能调用,这也是C语言中函数/变量声明的来源。
(4)链接过程中的顺序结构;链接过程链接器实际上是在链接脚本指导下完成的,则链接时的.o文件的顺序是由链接脚本指定的,若链接脚本中明确指定了顺序则会优先按照该规则指定的顺序排布,若链接脚本中没有指定具体的顺序则链接器会自动进行排布。
(5)顺序结构本质上符合CPU的设计原理,CPU是人设计的,则CPU的设计符合人的思考原理,则人的基本思考原理是顺序结构的。


39.4.程序调试的debug宏
(1)程序调试的常见方案-单步调试+裸机LED调试+打印信息+log文件;利用调试器进行单步调试(譬如IDE中或使用Jlink)适用于新手,最大的好处就是直观,能够帮助找到问题,缺点是限制性大+速度慢;裸机使用LED/蜂鸣器等硬件调试,适合单片机裸机程序;printf函数打印调试,比较常用,作为程序员必须学会使用打印信息调试,好处是具有普遍性,几乎在所有的情况下都能用;log文件(日志文件)是系统运行过程中在特定时候会打印某些调试信息,日志文件记录下来这些调试信息以供后续查找追查问题,适合于系统级或者大型程序的调试。
(2)打印信息不能太多也不能太少;调试信息太少会不够信息找到问题所在;调试信息太多会有大量的无用的信息淹没有用信息,导致有用信息无法看见,等于没有。
(3)调试(DEBUG)版本和发行(RELEASE)版本的区别;DEBUG版本就是包含了调试信息输出的版本,在程序测试过程中会发布debug版本,这种版本的程序运行时会打印出来调试信息/log文件,这些信息可以辅助测试人员判断程序的问题所在;DEBUG版本的坏处是输出调试信息占用了系统资源,拖慢了系统运行速度。因此DEBUG版本的性能低于RELEASE版本;RELEASE版本就是最终的发布版本,相较于DEBUG版本,其功能代码相同,但是去掉了所有的调试信息;适合最终测试通过要发布的程序,因为去掉了调试信息则程序的运行效率要更高。
(4)debug宏工作方式-若我们要输出DEBUG版本则在条件编译语句前加上#define_DEBUG即可,这样程序中的调试语句dbg()就会被替换成printf从而输出;如果我们要输出RELEASE版本则去掉#define_DEBUG,则dbg()就会被替换成空,则程序中所有的dbg()语句直接蒸发了,则该程序编译时就会生成没有任何调试信息的代码(见图3)。
(5)FILE等是C语言中的预定义宏,即这些宏由C语言自己定义的,这些宏具有特殊的含义,譬如FILE表示当前正在编译的c文件的文件名。


这里写图片描述


这里写图片描述


这里写图片描述


0 0