IOS开发之路--C语言预处理

2016-02-19 11:28 6 1 收藏

下面图老师小编跟大家分享一个简单易学的IOS开发之路--C语言预处理教程,get新技能是需要行动的,喜欢的朋友赶紧收藏起来学习下吧!

【 tulaoshi.com - 编程语言 】

概述

大家都知道一个C程序的运行包括编译和链接两个阶段,其实在编译之前预处理器首先要进行预处理操作,将处理完产生的一个新的源文件进行编译。由于预处理指令是在编译之前就进行了,因此很多时候它要比在程序运行时进行操作效率高。在C语言中包括三类预处理指令,今天将一一介绍:

宏定义 条件编译 文件包含

宏定义

对于程序中经常用到的一些常量或者简短的函数我们通常使用宏定义来处理,这样做的好处是对于程序中所有的配置我们可以统一在宏定义中进行管理,而且由于宏定义是在程序编译之前进行替换相比定义成全局变量或函数效率更高。

//// main.c// Pretreatment//// Created by Kenshin Cui on 14-6-28.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#include stdio.h#define PI 3.14 //宏定义一般大写#define R 10#define S 2*PI*R //在另一个宏里面引用了上面的宏int main(int argc, const char * argv[]) {  float r=10.5;  double area=PI*r*r;  printf("area=%.2fn",area);double a=S;  printf("a=%.2fn",a);  printf("PI=3.14n");//注意输出结果不是3.14=3.14而是PI=3.14,字符串中的PI并不会被替换#undef PI //强制终止宏定义,否则它的范围一直到文件结束  int PI=3.1415926;  double area2=PI*r*r;  printf("area2=%.2fn",area2);  return 0;}

宏定义实际的操作就是在预处理时进行对应替换,这个阶段不管语法是否正确,而且对于字符串中出现的宏名不会进行替换。宏定义的功能事实上是非常强大的,除了简单的常量替换还可以传入参数:

//// 1.2.c// Pretreatment//// Created by Kenshin Cui on 14-7-17.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#include stdio.h#define SUM(a,b) a+b#define SUB(a,b) (a-b)#define MUL (a,b) (a*b) //这么定义是错误的,预处理器会认为宏名为”MUL“,替换内容为”(a,b) (a*b)“int main(int argc, const char * argv[]) {int a=2,b=3,c,d;  c=SUM(a, b);  printf("c=%dn",c); //结果:c=5  d=SUM(a, b)*2;  printf("d=%dn"); //结果:8,为什么不是10呢?因为替换后:d=a+b*2也就是2+3*2=8int e=SUB(b, a)*2;  printf("(b-a)*2=%dn",e); //结果:2,如果SUB定义时不加括号这里应该是-1return 0;}

上面我们可以看出带参数的宏功能很强大,有点类似于函数,同函数不同的是它只是简单的替换,不涉及存储空间分配,参数、返回值等问题,但是由于它在预处理阶段展开,所以一般效率较高。使用带参数的宏需要注意的就是结果最好用括号括起来否则很容易出现问题(在上面的SUM例子中我们应该已经看到了);还有一点就是带参数的宏定义时名称和参数之间不要有空格。

条件编译

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

条件编译其实就是在编译之前预处理器根据预处理指令判断对应的条件,如果条件满足就将对应的代码编译进去,否则代码就根本不进入编译环节(相当于根本就没有这段代码)。

//// main.c// Pretreatment//// Created by Kenshin Cui on 14-06-28.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#include stdio.h#define COUNT 1int main(int argc, const char * argv[]) {  //判断是否定义了 COUNT 宏#if defined(COUNT) //等价于:#ifdef COUNT,相反如果判断没有定义过则可以通过#if !defined(COUNT)或者#ifndef COUNT  printf("COUNT definedn");#endif  //判断宏定义COUNT是否都与1#if COUNT==1  showMessage("hello,world!n");#else  say();#endifreturn 0;}

文件包含

文件包含指令#include在前面也多次使用过,这里再次强调一下。首先使用#include“xxx”包含和使用#include xxx包含的不同之处就是使用包含时,预处理器会搜索C函数库头文件路径下的文件,而使用“”包含时首先搜索程序所在目录,其次搜索系统Path定义目录,如果还是找不到才会搜索C函数库头文件所在目录。

另外在使用#include的时候我们需要注意包含文件的时候是不能递归包含的,例如a.h文件包含b.h,而b.h就不能再包含a.h了;还有就是重复包含虽然是允许的但是这会降低编译性能,不妨看一下下面的例子:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

上面有三段代码,在main.c和person.h中都包含了message.h而main.c自身又包含了person.h,这样程序在预处理阶段会对包含内容进行替换,替换后mian.c中包含了两个#include “message.h”虽然没有报错,但这会影响编译的性能,正确的做法应该是这样的:

其实就是用宏定义判断一个宏是否定义了,如果没有定义则会定义这个宏,这样以来如果已经包含过则这个宏定义肯定已经定义过了,即使再包含也不会重新定义了,下面的代码也就不会包含进去。

来源:http://www.tulaoshi.com/n/20160219/1597640.html

延伸阅读
1.图像平移 图像平移只是改变图像在屏幕上的位置,图像本身并不发生变化。 !-- frame contents -- !-- /frame contents -- 假设原图像区域左上角坐标为(x0, y0),右下角坐标为(x1, y1),将图像分别沿x和y轴平移dx和dy,则新图像的左上角坐标为(x0 +dx, y0+dy),右下角坐标为(x1+dx, y1+dy)。坐标平移变换公...
设置你的Shell 原文:http://www.redhat.com/developer/whitepapers/ intro_dev/shell.Html 作者:Nathan Thomas nthomas@redhat.com 翻译:yellowrose yellowrose@fun.21cn.com 版权:Red Hat Software,Inc.本文英文版遵循GNU GPL版本2 或更新版本,参见www.gnu.org/copyleft/gpl.html.中文版 为...
题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后天天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。 1.程序分析:采取逆向思维的方法,从后往前推断。 ...
题目:学习static定义静态变量的用法 1.程序分析: 2.程序源代码: #include "stdio.h" varfunc() { int var=0; static int static_var=0; printf("40:var equal %d ",var); printf("40:static var equal %d ",static_var); printf(""); var...
题目:请输入星期几的第一个字母来判定一下是星期几,假如第一个字母一样,则继续判定第二个字母。 1.程序分析:用情况语句比较好,假如第一个字母一样,则判定用情况语句或if语句判定第二个字母。 2.程序源代码: #include stdio.h void main() { char letter; printf("pl...

经验教程

461

收藏

79
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部