黑马程序员--04C预处理

------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------

预处理指令:

a.在编译前执行的指令

b. # 开头,句尾没有分号

c.主要分3种:宏定义、文件包含、条件编译 


1.宏

 记住一句话:宏纯粹是用来替换的

不带参数的宏定义

形式:

 #define 宏名    把这行代码后所有的宏名替换为它的值 (字符串中的不会被替换)

 宏名一般大写或者以字母k开头比如: #define kCount 4

 

宏定义定义常量

#define NUM 5        // 没有分号

 代码...

#undef NUM

在编译(翻译成010101)之前把文件中这行代码之后的所有NUM替换为5 (直到文件结束或者到#undef)


带参数的宏定义

形式

 #define 宏名(参数参数表达式      编译时把宏替换为宏后面的表达式

比如 #define sum(a, b) a + b    int a = sum(10, 10);   // 相当于 int a = 10 + 10;

注意

宏定义是纯粹的字符串替换所以写宏定义时,要用括号把每个参数和整个表达式都括起来。像这样:

#define sum(a, b) ((a) + (b))        // 记得用括号!

  比如如果用表达式作参数,假如我们定义了 #define mul(a,b) a * b, 然后用 int a = mul(1+2, 3+4) *  5 使用宏定义,它相当于 int a = 1 + 2 * 3 + 4 * 5= 37 而不是 3 * 7 * 5 = 105

#define pingfang(a) ((a)*a)
int main()
{
    int c = pingfang(5+5); // 替换之后就是(5+5)*5+5=55
    
    NSLog(@"%d",c);
    
    return 0;
    
}

带参数的宏定义和函数的区别

宏定义在编译前运算,函数在运行时运算,所以宏定义比函数更有效率(函数要在程序运行时进行运算,而这时宏定义在之前都运算完了),所以简单的函数,尽量用宏定义表示,提高效率。

没有运行检测(编译时会检测),只是纯粹的字符替换,所以自己要保证不要使用错了

没有参数和返回值的类型。

宏名不像函数名,不代表函数的地址,只能像上面那种方式使用。

 

宏定义的作用域

宏定义的位置可以在文件中的任意一行它的作用域从它所在那一行开始直到文件结束,或者到取消定义。

如果只需要在一段代码中使用宏定义,可以使用#undef来标记宏定义的结束,#undef之后的代码中的宏名不会被替换

#undef COUNT   // 取消宏定义从这行开始后面不再替换COUNT.


 
/*
 1.所有的宏以#开头,所以include是一个宏
 2.预处理指令分三种
   1宏定义
   2条件编译
   3文件包含 include
 3.预处理指令执行在编译称0和1之前
 4.预处理指令位置随便写
 5.作用域:从指令那一行开始,到文件结束
 6,宏名一般大写或者以k开头,变量名小写
 
 */

#import <Foundation/Foundation.h>

#define kCOUNT 4
int main()
{
    int a[] = {1,23,4,5};
    
    for (int i = 0;i<kCOUNT;i++)
    {
        NSLog(@"%d-",a[i]);
    }
    return 0;
    
}
#undef kCOUNT


 

2.条件编译

通常情况下,所有的代码都会被编译。但是有时我们希望程序中的一部分代码,只有在满足一定条件时才被编译和执行。

格式

#if 条件1

.... code ....

#else

.... code ....

#else

.... code ....

#endif        // 一定要有 endif

 

条件判断

编译要用宏定义来做判断

#define NUM 10   //  a > 0  这样是不可以的,因为编译前是不知道a的值的

#if NUM > 0

代码

#elif

代码

#else

代码

#endif

这样才是可以的,因为#define#if都是预处理指令,编译前处理的

因为条件编译只编译部分的代码,所以效率更高。

 

其它用法:判断是否定义过某个宏 

方法一: defined()  !defined()

#if defined(NUM)

code

#endif

如果定义过NUM这个宏(不看NUM的值),才编译这段代码

 

方法二: #ifdef  #ifndef

#ifndef NUM

code

#endif

如果没有定义NUM这个宏,才编译这段代码

 

3.文件包含

文件包含就是把一个文件的内容全部拷贝到这个文件中

#include < > 

#include " "

 前者会直接到C语言库函数头文件目录中寻找相应的文件;后者会先在源程序所在目录中寻找,如果没有,再到系统path里寻找,如果没有,再到库函数头文件目录里寻找

通常把C语言的库函数用<>包含,自己写的头文件用 " " 包含

注意

a.可以嵌套包含,不可以递归包含

嵌套包含:比如a.h包含(include)b.hb.h包含c.h,是可以的,import可以避免重复包含

递归包含:比如 a.h包含了b.hb.h包含了a.h(相互包含),是不可以的,会报错

b.一个文件中如果多次包含同一个头文件,函数被重复声明,可以运行, 但是会降低编译效率。

如何避免多次包含同一个头文件

在自定义的头文件的前面,加上这么一段

#ifndef _NAME_ // 名字随意,但要保证不同头文件里面的名字不同,所以起名时最好根据文件名来起名

#define _NAME_  

(#include a.h)     // 有可能引用别的头文件

头文件中的声明

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值