C语言宏定义和宏定义函数
要写好C语言,漂亮的宏定义是非常重要的。宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。
在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。
我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义:
#define MAX( a, b) ( (a) > (b) (a) : (b) )
其次,把它用函数来实现:
int max( int a, int b)
{
return (a > b a : b)
}
很显然,我们不会选择用函数来完成这个任务,原因有两个:首先,函数调用会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。这种开销不仅会降低代码效率,而且代码量也会大大增加,而使用宏定义则在代码规模和速度方面都比函数更胜一筹;其次,函数的参数必须被声明为一种特定的类型,所以它只能在类型合适的表达式上使用,我们如果要比较两个浮点型的大小,就不得不再写一个专门针对浮点型的比较函数。反之,上面的那个宏定义可以用于整形、长整形、单浮点型、双浮点型以及其他任何可以用“>”操作符比较值大小的类型,也就是说,宏是与类型无关的。
和使用函数相比,使用宏的不利之处在于每次使用宏时,一份宏定义代码的拷贝都会插入到程序中。除非宏非常短,否则使用宏会大幅度增加程序的长度。
还有一些任务根本无法用函数实现,但是用宏定义却很好实现。比如参数类型没法作为参数传递给函数,但是可以把参数类型传递给带参的宏。
看下面的例子:
#define MALLOC(n, type) \
( (type *) malloc((n)* sizeof(type)))
利用这个宏,我们就可以为任何类型分配一段我们指定的空间大小,并返回指向这段空间的指针。我们可以观察一下这个宏确切的工作过程:
int *ptr;
ptr = MALLOC ( , int );
将这宏展开以后的结果:
ptr = (int *) malloc ( () * sizeof(int) );
这个例子是宏定义的经典应用之一,完成了函数不能完成的功能,但是宏定义也不能滥用,通常,如果相同的代码需要出现在程序的几个地方,更好的方法是把它实现为一个函数。
下面总结和宏和函数的不同之处,以供大家写代码时使用,这段总结摘自《C和指针》一书。
example:
define的单行定义
#define maxi(a,b) (a>;b?a:b)
define的多行定义
define可以替代多行的代码,例如MFC中的宏定义(非常的经典,虽然让人看了恶心)
#define MACRO(arg1, arg2) do { \
\
stmt1; \
stmt2; \
\
} while()
关键是要在每一个换行的时候加上一个 "\ "
//宏定义写出swap(x,y)交换函数
#define swap(x, y)\
x = x + y;\
y = x - y;\
x = x - y;
zigbee里多行define有如下例子
#define FillAndSendTxOptions( TRANSSEQ, ADDR, ID, LEN, TxO ) { \
afStatus_t stat; \
ZDP_TxOptions = (TxO); \
stat = fillAndSend( (TRANSSEQ), (ADDR), (ID), (LEN) ); \
ZDP_TxOptions = AF_TX_OPTIONS_NONE; \
return stat; \
}
C语言宏定义和宏定义函数的更多相关文章
- C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数
在定义可变参数的函数之前,先来理解一下函数参数的传递原理: 1.函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈. 2.参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在 ...
- 【C语言】预处理、宏定义、内联函数 _
一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的 ...
- 【C语言】预处理、宏定义、内联函数
一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的汇编 ...
- C语言 预处理二(宏定义--#define)
//#define 宏定义(宏定义一般大写) //知识点一-->#define的作用域:从#define开始,从上往下,如果遇到#undef就到#undef处结束,如果没有就是作用于当前整个文件 ...
- __inline定义的内联函数和宏的区别
转自:http://blog.csdn.net/lw370481/article/details/7311668 函数与宏 #define TABLE_COMP(x) ((x)>0?(x):0) ...
- 预定义宏,C语言预定义的宏详解
1.预定义宏 对于预定义宏,相信大家并不陌生.为了方便处理一些有用的信息,预处理器定义了一些预处理标识符,也就是预定义宏.预定义宏的名称都是以"__"(两条下划线)开头和结尾的,如 ...
- C语言宏的定义和宏的使用方法(#define)
1.宏的功能介绍 在 C 语言中,可以采用命令 #define 来定义宏.该命令允许把一个名称指定成任何所需的文本,例如一个常量值或者一条语句.在定义了宏之后,无论宏名称出现在源代码的何处,预处理器都 ...
- linux 中C语言便于调试的宏定义编写及 __FILE__,__FUNCTION__, __LINE__参数使用
转自:http://blog.csdn.net/edonlii/article/details/8491342/ 在linux编程中,当文件数量变的众多之后,使用gdb调试就是一场灾难.因此在程序中加 ...
- 易出错的C语言题目之一:宏定义与预处理
1.写出下列代码的运行结果: #include<stdio.h> #include<string.h> #define STRCPY(a,b) strcpy(a##_p,#b) ...
随机推荐
- java EE : http 协议之请求报文、响应报文
1 HTTP协议特点 1)客户端->服务端(请求request)有三部份 a)请求行 b)请求头 c)请求的内容,如果没有,就是空白字符 2)服务端->客户端(响应response)有三部 ...
- python平均值和加权平均值
In [15]: import numpy as np In [16]: a=(70,80,60) In [17]: np.mean(a) #平均值 Out[17]: 70.0 In [18]: np ...
- 【WPF】自定义控件之远程图片浏览
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
- thinkphp5.0安装
ThinkPHP5的环境要求如下: PHP >= 5.4.0 PDO PHP Extension MBstring PHP Extension CURL PHP Extension 严格来说,T ...
- 长沙理工大学第十二届ACM大赛-重现赛 L - 选择困难症
题目描述 小L有严重的选择困难症. 早上起床后,需要花很长时间决定今天穿什么出门. 假设一共有k类物品需要搭配选择,每类物品的个数为Ai,每个物品有一个喜欢值Vj,代表小L对这件物品的喜欢程度. 小L ...
- Mac os 下的文件权限管理
Mac os 下的文件权限管理 命令 ls -l -A 结果 -rw-r--r-- 1 user admin 2326156 4 12 15:24 adb 横线代表空许可.r代表只读,w代表写,x代表 ...
- 数据仓库之父——Bill Inmon(转载)
从此处转载 http://blog.sina.com.cn/s/blog_615f9dba0100f67p.html 比尔·恩门(Bill Inmon),被称为数据仓库之父,最早的数据仓库概念提出者, ...
- 可以在GitHub或者码云里 直接搜索 项目 比如 哔哩哔哩
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha Search · 哔哩哔哩 哔哩哔哩 · 搜索 - 码云 还有就是 以前的项目 可以不要 ...
- NOIP2017 D2T1奶酪
这题终于是正经第一题感觉了. 只需要对相交或相切的球建一条边,然后对所有与底面有交点的球连边,再对所有与顶面有交点的球连边,bfs判断上下连通性即可. #include<iostream> ...
- 【8.22校内测试】【数学】【并查集】【string】
今天的t2t3能打出来80分的暴力都好满足啊QwQ.(%%%$idy$ 今天的签到题,做的时候一眼就看出性质叻qwq.大于11的所有数分解合数都可以用4.6.9表示,乱搞搞就可以了. #include ...