一、理论
1、什么是预编译,何时需要预编译?
答: 预编译又叫预处理,指程序编译前的代码文本处理工作。
主要指用#表示的预编译指令,有三种:编译器编译前拷贝#include包含的代码,#define宏定义的替换,条件编译等等。
何时需要预编译?
1)总是使用不经常改动的大型代码体。
2)程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。
2、为什么标准头文件都有类似以下的结构?
#ifndef __INCvxWorksh
#define __INCvxWorksh //防止该头文件被重复引用
extern "C" //实现C++与C混合编程
{
#include "cExample.h"
}
#endif /* __INCvxWorksh */
答:extern “C”声明实现C++与C及其它语言的混合编程。
C++作为面向对象的语言,支持函数重载,而过程式语言C则不支持。同一函数被C++编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo(int x, int y);
该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。
为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了。
3、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
答: c用宏定义,c++用inline。
二、define表达式
【1】好处:直观;帮忙计算;
【2】语法规则(无分号;使用括号;防止溢出;小心输入自加自减的参数)
1、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
1) #define 语法的基本知识(不能以分号结束,括号的使用)
2)懂得预处理器将计算常数表达式的值,直接写出怎么样计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3) 这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是无符号的长整型数。
2、写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A)<=(B)?(A):(B))
或者
#define Min((X),(Y)) ((X)>(Y)?(Y):(X))
【1】三重条件操作符使得编译器能产生比if-then-else更优化的代码。要小心地把参数和整个宏用括号括起来。
【2】MIN(*p++, b)会产生宏的副作用,指针p会作2次++自增操作。所以这个宏定义表达式不能代入自加自减。
3、已知一个数组table,用一个宏定义,求出数据的元素个数?
#define NTBL (sizeof(table)/sizeof(table[0]))
4、用宏定义写出swap(x,y)
#define SWAP(x,y) {x+=y;y=x-y;x=x-y;}
5、一语句实现x是否为2的若干次幂的判断
#define is2*n(x) ((x & (x - 1))? 0 : 1)
int main(void)
{
int m = 512;
cout << ((m & (m - 1)) ? false : true) << endl;
return (0);
}
答:x为2的若干次幂即表示x中只有最高位为1。
题目转化为求一个32位数中1的位数,如果为1,则表示该数为2的若干次幂。
//这个时候 x: 0B10 0B100 0B1000 0B10000
//这个时候 x-1: 0B1 0B11 0B111 0B1111
若有两个及以上的1,则(m & (m - 1))不为0,输出0,表示不为2的若干次幂;
同理也可以利用此规则求一个32位数中1的位数, (m & (m - 1)每次可用消除一个1,计算的次数即为1的个数 !
三、define的其他用法
1、预编译
#if 0
#elif 0
#elif 0
#elif 1
#endif
2、宏定义操作IO
#define digitalHi(p,i) {p->BSRR=i;} //输出为高电平
#define digitalLo(p,i) {p->BRR=i;} //输出为低电平
#define digitalToggle(p,i) {p->ODR^=i;} //输出为反转状态
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1(a) if (a) \
GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);\
else \
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN)
3、替代函数语句
#define IS_BLCOM_NOMAL_MODE() (g_BlcomState==EM_BLCOM_IDLE)
if(IS_BLCOM_NOMAL_MODE())
{
...
}