c语言中宏和函数 条件编译相关的预编译指令

宏和函数的区别
宏:

#define MAX(a,b) ((a)>(b)?(a):(b))

函数:

MAX(a,b) {return a>b?a:b}

宏和函数的区别:

1.宏是与类型无关的;

但函数是跟类型有关的,如果参数的类型不同,就需要使用不同的函数,即使他们执行的任务是相同的;

2. 宏可能会带来运算优先级的问题,导致运算结果出错;

3.宏的参数替换是直接替换的,不经过任何计算;

    而函数调用时会将实参的值传给形参;

4.宏是没法调试的,因为宏是在编译之前进行(先用宏体替换宏名,再进行编译);

  而函数是在编译之后执行时才调用的;

5.宏的参数是不占内存空间的,因为只做字符串的替换;

   而函数调用时参数之间的传递,所以占用内存;

6.宏的速度比函数速度快,因为函数有调用和返回时间的开销,在函数调用时它既要保存现场又要跳转到另一个函数调用中去执     行,然后还要返回现场,但宏函数中就不存在;

7.宏在传参时可以传类型,但是函数不能传类型;

8.宏不能递归,函数可以递归;

本文主要介绍c语言中条件编译相关的预编译指令,包括#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined。

一:条件编译
条件编译是根据实际定义宏(某类条件)进行代码静态编译的手段。可根据表达式的值或某个特定宏是否被定义来确定编译条件。

最常见的条件编译是防止重复包含头文件的宏,形式跟下面代码类似:

1 #ifndef ABCD_H
2 #define ABCD_H
3 
4 // ... some declaration codes
5 
6 #endif // #ifndef ABCD_H


在实现文件中通常有如下类似的定义:

1 #ifndef ABCD_H
2 #define ABCD_H
3 
4 // ... some declaration codes
5 
6 #endif // #ifndef ABCD_H

这些都是条件编译的常用情境。三、条件编译中使用的预编译指令

#define            定义一个预处理宏
#undef            取消宏的定义

#if                   编译预处理中的条件命令,相当于C语法中的if语句
#ifdef              判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef            与#ifdef相反,判断某个宏是否未被定义
#elif                若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else              与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif             #if, #ifdef, #ifndef这些条件命令的结束标志.
defined          与#if, #elif配合使用,判断某个宏是否被定义

四、预编译指令应用举例
1. #define、#undef
#define命令定义一个宏:

#define MACRO_NAME[(args)] [tokens[(opt)]]


之后出现的MACRO_NAME将被替代为所定义的标记(tokens)。宏可带参数,而后面的标记也是可选的。

宏定义,按照是否带参数通常分为对象宏、函数宏两种。
对象宏: 不带参数的宏被称为"对象宏(objectlike macro)"。对象宏多用于定义常量、通用标识。例如:

// 常量定义

#define MAX_LENGTH 100


// 通用标识,日志输出宏

#define SLog printf


// 预编译宏

#define _DEBUG


函数宏:带参数的宏。利用宏可以提高代码的运行效率: 子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源。 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率。但多数c++程序不推荐使用函数宏,调试上有一定难度,可考虑使用c++的inline代替之。例如:

// 最小值函数

#define MIN(a,b) ((a)>(b)? (a):(b))


// 安全释放内存函数

#define SAFE_DELETE(p) {if(NULL!=p){delete p; p = NULL;}}


#undef可以取消宏定义,与#define对应。

2. defined
defined用来测试某个宏是否被定义。defined(name): 若宏被定义,则返回1,否则返回0。
它与#if、#elif、#else结合使用来判断宏是否被定义,乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef。defined可用于在一条判断语句中声明多个判别条件;#ifdef和#ifndef则仅支持判断一个宏是否定义。

#if defined(VAX) && defined(UNIX) && !defined(DEBUG) 


和#if、#elif、#else不同,#ifdef、#ifndef、defined测试的宏可以是对象宏,也可以是函数宏。

3. #ifdef、#ifndef、#else、#endif
条件编译中相对常用的预编译指令。模式如下:

#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC 

#ifdef用于判断某个宏是否定义,和#ifndef功能正好相反,二者仅支持判断单个宏是否已经定义,上面例子中二者可以互换。如果不需要多条件预编译的话,上面例子中的#elif和#else均可以不写。

4. #if、#elif、#else、#endif
#if可支持同时判断多个宏的存在,与常量表达式配合使用。常用格式如下:

#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif

常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏, 那么它的值被视为0。

#if MACRO_NON_DEFINED // 等价于

#if 0
在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。
注意: #if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。

总结
本文主要介绍c语言中有关预编译的指令。撰写本文的目的在于理清相关概念调用,在后续预编译使用时可以找到最合适的指令及格式。比如同时满足多个宏定义的预编译、多分支预编译、#elif和#else指令的配合等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值