C语言07 预编译+define

一、理论

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()) 
{
    ...
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值