C语言预处理

目前我并没有windows软件编写经验,对C语言的应用也仅限于各种单片机的编程,所以对预处理的理解也只限于单片机程序上。不过我想,C语言是ANSI的,所以这个总结也算是很全面了吧。

#define和#include是最常用的预处理,单片机程序不用其他预处理也完全可行。所以初学者并不深究预处理的应用。

我也只是初学者而已,但是发现预处理可以用简便的语句实现很强大的功能,真的很有趣,于是小小研究了一下。

分类解释

在编译器编译之前,会首先搜索预处理指令,按照指令完成编译,预处理又分为:文件包含、条件编译、布局控制(杂注)和宏替换。

文件包含:

#include""和#include<>,前者是和该c文件相同目录下的.h,如 #include “os_cfg.h” ,或指明路径的.h,如 #include “\software\ucos-ii\source\ucos_ii.h” ;

后者是编译器系统路径中的.h,一般C语言标准库函数在编译器里集成,如 #include <stdio.h> 。

只要包含了.h,而.h里有函数声明(或变量、结构体实例),那么不论这个函数(变量、结构体实例)在那个.c文件里定义的,都可以在主C文件中使用。

对于函数,可以按功能分类成各种模块,集合在一起写成一个.c文件,然后作同名的.h给出函数声明,如果模块太多,也可以再用一个.h来包含各模块的.h,uCOS-II中的includes.h就是这样。

对于变量,C模块中的全局变量只对该模块有效,如果想要被其他C文件访问,就得在.h里声明,如果主C包含了这个.h,那么此变量就成了真正全局的了。

对于结构体实例,其结构的定义可以放在.h里,(如果不需要到处定义很多实例放在c里也可以),实例定义在c里,而声明放在.h里,这样就到处可用此实例了。

#include 的对象直接被插入到了该位置,所以可能出现#include重复甚至嵌套,用#ifndef…#define…代码…#endif的方法可以保证重复包含的.h那个只在第一次出现时编译.

条件编译:

上面的#ifndef就是条件编译的一种。条件编译主要用于跳过某些代码不编译,这样可以用来写一个C文件,但是适应不同硬件版本,或者可采用不同算法。我就经常用多种算法写同一个功能,#define method 1,#if methof==1…#endif, #if method ==2…#endif

Protothread的神奇功能就是用宏和条件编译来实现的。举个例子:

#define LC_INIT(s) s = 0;

#define LC_RESUME(s) switch(s) { case 0:

#define LC_SET(s) s = LINE; case LINE:

#define LC_END(s) }

#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)

每个线程执行一次 PT_BEGIN(pt),这样就创建了一个switch,一开始 pt->lc=0, PT_BEGIN(pt)之后继续执行语句(本protothread的语句,一般是while(1)),执行到PT_WAIT_UNTIL(pt, condition)之类会调用LC_SET((pt)->lc);然后return,于是pt->lc记录了行号,创建了case:,下次进到线程之直接走 LC_RESUME(s)里的switch到上次的位置

布局控制/杂注:

主要是#pragma,从实用的角度讲,就是编译器为了简化用户操作,给用户提供了一些命令,不同编译器是不一样的,比如,IAR EW430就可以直接定义中断函数而不用管中断向量表在哪儿。(比如ARM7就要编译前手动改程序段的中断向量表,DSPF2812就要用程序指令改数据段的中断向量表,而51则由keil自动放置中断跳转指令。)

#pragma vector=PORT1_VECTOR

__interrupt void Port_1(void)

{

//code

}

编译器会自动给中断函数指定中断向量。

宏替换:

宏函数其实可以巧妙的代替函数,尤其是很短又没有局部变量的一些语句,还可以代换很多复杂的格式,如

#define F “%6.2f”

#define F3 F “\t” F “\t” F"\t\n"

用函数printf(F3,a,b,c),可以同时指定a,b,c 的格式

其他:

预定义标识符

为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但是他们都会处理下面的4种:

FILE 正在编译的文件的名字

LINE 正在编译的文件的行号

DATE 编译时刻的日期字符串,例如: “25 Dec 2000”

TIME 编译时刻的时间字符串,例如: “12:30:55”

发布了302 篇原创文章 · 获赞 5 · 访问量 6325
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览