嵌入式C语言之零碎知识

***操作系统:
   裸机程序:代码量小,功能简单,所有的代码都和直接的目的有关,没有服务性代码。 
   操作系统:管理阶级,其代码本身不直接产生价值,他的主要目的是管理所有的资源,为直接工作的程序提供服务(例如分配内存)。操作系统既是管理者也是服务者。
   
   操作系统的调用通道:API函数。
   操作系统负责管理和资源分配,应用程序负责具体的直接操作。当应用程序需要使用系统资源(内存,cpu,硬件操作)时,通过API向操作系统发出申请。然后操作系统响应申请帮助应用程序执行程序。
   
   c库函数与API:
   单纯的API只是提供了极简单没有任何封装的服务函数,这些函数应用程序时可用的,但是不太好用。应用程序为了好用,就对API进行二次封装,把它变得好一些,于是就成了c库函数。 有时同一个功能API和库函数都可以完成。
   
   不同的操作系统有不同的API,只是完成一个任务所调用的API不同,库函数在不同的操作系统也不同,但是相似度要更高些。(人们下意识屏蔽不同操作函数的差异,因此在封装API成库函数时,尽量使用了同一套接口,所以库函数相似度很高。于是就出现了可移植性。)
   
   操作系统的意义:软件体系分工。
   
***main函数的返回值:
   函数被另一个函数调用,返回值作为函数式的值返回给调用这个函数的地方。
   main函数是整个程序的入口。其他的函数只有直接或者间接调用,才能被执行。而main函数从某种角度来看代表了整个程序。main函数的开始和结束代表着整个函数的起始。
   linux中一个新程序执行的本质:通过./x;通过shell脚本来调用执行;本质都是一个进程的创建,加载,运行,消亡。linux执行一个程序就是创建一个新的进程,然后将这个程序丢进这个程序中去执行知直到结束。
   
   main返回给调用这个函数的父进程。
   argc和argv:argc是int类型,表示main函数运行时传入的参数个数;agrv是字符数组,表示传入main函数的具体参数。
   mian函数的传参是通过字符串传进去的,程序被调用传参时,各个参数之间是通过空格来间隔的,
   

***void类型的本质:修饰一个目前还未确定类型的变量。
   当描述还没有具体使用的内存时需要用void来修饰。
   void的一个经典案例就是malloc的返回值。malloc向系统的堆内存管理器申请一段内存给当前的程序使用,它返回的是一个指针,这个指针指向刚才申请的内存。但是malloc函数无法知道内存里即将存放的变量类型,所以malloc无法返回具体类型的指针。于是返回了一个void*类型的指针,为程序分配一块干净的内存。

   C语言是强类型语言,所有的变量都有自己固定的类型,有自己固定的内存占有,有固定的解析方式。
   数据类型的本质含义决定了变量的内存占有数和内存的解析方法。
   在内存还未和具体的变量绑定的时候,内存是没有类型的。内存知识因为和具体的变量相关联了才有了确定的类型。
   
   
***NULL:标准定义:
   #ifdef _cplusplus
   #define NULL 0
   #else
   #define NULL (void *)0
   #endif 
   NULL的本质是0,但是0不是当一个数字来解析的,而是当一个内存地址来解决的。(void *)0这个整体表达式表示一个指针,这个指针长度为4(32位操作系统)/8(64位),其地址取决于指针变量自己本身,但是指针变量的值是0。也就是这个指针变量指向0地址(实际上是0地址开始的一段内存)。
   使用定义一个未赋值的指针变量时可以使用null避免出现野指针。
   
   null的作用:1.使得野指针指向0地址以保证其安全;
               2.做一个特殊的标记。标准的指针使用步骤如下:
               int *p=NULL;
               p=xx;
               if(NULL!=p)   //if(p!=NULL)的话,出现少写!时编译器不会报错,前面的写法可以避免。
               {
                  *p;   //在确认p不等于NULL的情况下去解引用NULL
               }
               p=NULL;    //用完后p再次等于NULL
               
   NULL和“\0”的区别:
   1.'\0'是一个转义字符,对应的ascll编码值是0,本质也是0。‘\0’是字符串结尾的标志,用来判断字符串是否到头;
   2.‘0’是一个字符,对应的ascll编码值是48,本质也是48。一般用来获取0的ascll码值;
   3.NULL是一个表达式,是强制类型转换为void*类型的0,本质是0。一般用来比较指针是否为一个野指针。
   
   高级语言对汇编进行了封装,给程序员提供了一些接近人类思维的语法特征,不用太过于考虑机器的原理。
   强制类型转化时编译器会在系统之中分配一定的内存来定义一个临时变量,将要进行数据转化的数据进行备份,转化之后将新值赋值给规定的变量,整个过程不会将原变量改变。
   
   
***程序调试的debug宏:
   使用log文件(日志文件),系统会在运行过程中特定的时候打印一些调试信息。日志文件记录下来这些调试信息以供日后查看。
   
   debug版本包含了调试信息的输出版本,在程序测试过程会发布,这种版本的程序运行时会打印出来调试信息/log文件,这些信息可以辅助测试人员判断程序的问题,但是大量的输出调试文件占用了系统资源,拖慢了系统的运行速度。
   release版本是最终的发行版,去掉了调试信息,程序的运行效率更高。
   debug和release版本其实一套源代码,其中有很多的打印调试信息语句,通过条件编译宏debug宏
   
   debug宏的原理:
   #ifdef DEBUG
   #define dbg()   printf()
   #else
   #define 
   #define dbg()
   #endif
   工作方式:如果要输出DEBUG版本则在条件编译语句前加上#define ,这样程序中的调试语句dbg()就会被替换成后面的printf从而输出;如果我们要输出 release版本则去掉#define DEBUG ,则dbg()就会被替换成空,编译时就没有任何的调试信息。
  

猜你喜欢

转载自blog.csdn.net/weixin_40647352/article/details/84075188