1.预处理
1.1define
宏定义和函数有何区别?
宏在编译时完成替换,之后被替换的文本参与编译,相当于直接插入了代码,运行时不存在函数调用,执行起来更快;函数调用在运行时需要跳转到具体调用函数。
宏函数属于在结构中插入代码,没有返回值;函数调用具有返回值。
宏函数参数没有类型,不进行类型检查;函数参数具有类型,需要检查类型。
宏函数不要在最后加分号。
宏定义和const区别?
宏替换发生在编译阶段之前,属于文本插入替换;const作用发生于编译过程中。
宏不检查类型;const会检查数据类型。
宏定义的数据没有分配内存空间,只是插入替换掉;const定义的变量只是值不能改变,但要分配内存空间。
宏定义和typedef区别?
宏主要用于定义常量及书写复杂的内容;typedef主要用于定义类型别名。
宏替换发生在编译阶段之前,属于文本插入替换;typedef是编译的一部分。
宏不检查类型;typedef会检查数据类型。
宏不是语句,不在在最后加分号;typedef是语句,要加分号标识结束。
注意对指针的操作,typedef char * p_char和#define p_char char *区别巨大。
宏定义和内联函数(inline)区别?
在使用时,宏只做简单字符串替换(编译前)。而内联函数可以进行参数类型检查(编译时),且具有返回值。
内联函数本身是函数,强调函数特性,具有重载等功能。
内联函数可以作为某个类的成员函数,这样可以使用类的保护成员和私有成员。而当一个表达式涉及到类保护成员或私有成员时,宏就不能实现了。
条件编译#ifdef, #else, #endif作用?
可以通过加#define,并通过#ifdef来判断,将某些具体模块包括进要编译的内容。
用于子程序前加#define DEBUG用于程序调试。
应对硬件的设置(机器类型等)。
条件编译功能if也可实现,但条件编译可以减少被编译语句,从而减少目标程序大小。
1.2 ifdef
1.3 endif
说一下理解 ifdef endif
一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。
条件编译命令最常见的形式为:
#ifdef 标识符
程序段1
#else
程序段2
#endif
它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。
其中#else部分也可以没有,即:
#ifdef
程序段1
#denif
在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件上时,就会出现大量“重定义”错误。在头文件中使用#define、#ifndef、#ifdef、#endif能避免头文件重定义。
2.volatile
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。
遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,
从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt;
当要求使用 volatile 声明的变量的值的时候,
系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。
而且读取的数据立刻被保存。
volatile用在如下的几个地方:
1) 中断服务程序中修改的供其它程序检测的变量需要加volatile;
2) 多任务环境下各任务间共享的标志应该加volatile;
3) 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;