C语言宏定义函数

以下内容源于网络资源的学习与整理,如有侵权请告知删除。

在软件开发过程中,经常有一些常用的代码段,这些常用的代码段既可以写成函数,也可以封装成宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。

宏定义函数 VS 函数

我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义:

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

其次,把它用函数来实现:

int max( int a, int b)
{return ((a>b)? a:b);
}

使用函数的坏处

很显然,我们不会选择用函数来完成这个任务,原因有两个:

(1)首先,函数调用会带来额外的开销。它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。这种开销不仅会降低代码效率,而且代码量也会大大增加,而使用宏定义则在代码规模和速度方面都比函数更胜一筹;

(2)其次,函数的参数必须被声明为一种特定的类型,因此函数只能在类型合适的表达式上使用。比如我们如果要比较两个浮点型的大小,就不得不再写一个专门针对浮点型的比较函数。反之,上面的那个宏定义可以用于整形、长整形、单浮点型、双浮点型以及其他任何可以用“>”操作符比较值大小的类型,也就是说,宏是与类型无关的

使用宏的好处与坏处

和使用函数相比,使用宏的不利之处在于每次使用宏时,一份宏定义代码的拷贝都会插入到程序中。除非宏非常短,否则使用宏会大幅度增加程序的长度。

但是宏定义可以完成一些用函数无法实现的任务,比如不可以将参数类型作为参数传递给函数,但是可以把参数类型传递给带参的宏。

看下面的例子:

#define MALLOC(n,type) (  (type *) malloc((n)*sizeof(type))  )

利用这个宏,我们就可以为任何类型分配一段我们指定的空间大小,并返回指向这段空间的指针。我们可以观察一下这个宏确切的工作过程。

int *ptr;
ptr = MALLOC ( 5, int );//将这宏展开以后的结果:ptr = (int *) malloc ( (5) * sizeof(int) );

这个例子是宏定义的经典应用之一,完成了函数不能完成的功能。但是宏定义也不能滥用,通常,如果相同的代码需要出现在程序的几个地方,更好的方法是把它实现为一个函数。

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;                                        \
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

壊小子的学习【日常阅读篇】(三)常规学习类图书

在上一篇职业相关图书中也提到过目前的职业方向,其中项目经理、产品经理是未来的发展方向,因此这类的书也就成为了常规类的学习用书。另外还包括的是工商管理类图书、心理学类、法律类以及外语类。 工商管理是准备续的本科,虽然是交钱就能拿到…

【原】webpack--plugins,主要解释plugins干了啥

其实呢,plugins是增强webpack的功能, 插件用于bundle文件的优化,资源管理和环境变量的注入, 可以理解为任何loaders不能做的事让它来做, 作用于整个构建过程。 常见的plugins有哪些? CommonsChunkPlugin: 将…

hadoop2.2.0 分布式存储hdfs完全分布式搭建及功能测试记录(一)----架构及原理介绍...

0.文档说明:本文是围绕hadoop2.2的分布式文件系统hdfs进行分布式存储功能测试,形成的hdfs分布式存储功能测试报告,其中主要包括三大部分内容:第一部分介绍了hdfs的基本原理;第二部分介绍了hadoop2.2的完全分布式集群安…

宏定义函数container_of的解释

从kernel里面抠出的一些与宏container_of有关的代码,如下: 1、此宏作用是从结构体的某元素(member)出发,得到结构体的首地址; 2、container_of的参数解释 (1)type:指的是…

【ASP.NET Web API教程】2.3 与实体框架一起使用Web API

2.3 Using Web API with Entity Framework 2.3 与实体框架一起使用Web API 本小节是ASP.NET Web API第2章的第3小节,原文共分为7个部分,分成了7篇文章,故这里也分为7个帖子贴出,以下是本小节的第1部分 — 译者注。 Part 1: Overvi…

【原】webpack--文件监听的原理

轮询判断文件的最后编辑时间是否发生变化,一开始有个文件的修改时间,先存储起来这个修改时间,下次再有修改就会和上次修改时间比对,发现不一致的时候不会立即告诉监听者,而是把文件修改缓存起来,等待一段时…

ITTC数据挖掘平台介绍(综述)——平台简介

数据挖掘方兴未艾,大量新事物层出不穷。本系列将介绍我们自主设计的数据挖掘软件平台。与大家共同分享对知识,微博,人际等复杂网络的分析,以及对自然语言处理的见解。 一、我们需要怎样的数据挖掘系统 一直以来,以高校…

Linux—程序包安装与管理

1、软件包是对于一种软件所进行打包的方式。在不同的操作系统中,软件包的类型有很大的区别。对于Linux系统中,软件包主要以两种形式出现:二进制包以及源代码包。二进制包:1)传统的red hat linux二进制包2)d…

strlen()函数 与 sizeof运算符

以下内容源于网络资源的学习与整理,如有侵权请告知删除。欢迎交流。 一、strlen()函数 函数模型 size_t strlen(const char *s); 函数作用 strlen()函数是C库函数,其功能是计算字符串长度。 即从代表该字符串的第一个地址开始遍历,直到遇到‘…

Master-Detail(主表明细),确认可以出货的SQL指令 -- Not Exists

这是我文章的备份,原文请看: http://www.dotblogs.com.tw/mis2000lab/archive/2011/08/18/master_detail_finish_and_shipping.aspx [补充]下集,第十四章。Master-Detail(主表明细),确认可以出货的SQL指令…

开发板——X210开发板的SD卡启动方式

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 前言与总结 这里说的SD卡启动方式,指的是uboot在SD卡中或者在inand里,且启动介质拨码开关选择SD卡启动方式(对于X210,是拨到远离电源键的一侧&#xf…

使用iBATIS3.0完成增删改查

为什么80%的码农都做不了架构师?>>> 使用iBATIS3.0完成增删改查 iBATIS3.0和以前的版本有一些改变,不过学过以前版本的再学习3.0应该不是太难,3.0要求JDK1.5支持,因为其中增加了注解和泛型,这些都是JDK1.5…

oracle-11g-R2监听文件配置

客户端连接oracle数据库时出现如下错误: Listener refused the connection with the following error: ORA-12514, TNS:listener does not currently know of service requested in connect descriptor 首先看看Oracle服务是否开启: 然后找到listener.or…

【C】strcpy()需谨慎使用;

大家都知道C中的strcpy()函数是用来复制字符串的库函数。先附上代码看看strcpy()函数的功能&#xff1a; 1 #include<stdio.h>2 #include<string.h>3 #define MAX 204 5 int main(void)6 {7 char a[MAX]"abc";8 char b[MAX]"abcdefghi"…

多重指针操作

之前对多重指针操作心存忐忑&#xff0c;不能很熟练使用&#xff0c;本质原因是不了解其实质&#xff0c;因此对其进行了学习。 一、简单的代码如下 #include <stdio.h> #include <stdlib.h> #include <string.h>void myArray(char ***p2, int num) {int i0;…

C++ 初始化与赋值

1、初始化与赋值的区别&#xff1a; 二者的区别不是看&#xff0c;是否有这个赋值操作符&#xff0c;而是看操作的时候&#xff0c;对象是否已经有值。 初始化&#xff1a;创建对象&#xff0c;并给它设置初始值。 赋值&#xff1a;对象已经有值&#xff0c;擦除对象的当前值&a…

如何找出MySQL数据库中的低效SQL语句

面对业务的迅猛发展&#xff0c;DBA的一项重要工作就是及时发现数据库中的低效SQL语句&#xff0c;有的可以立刻着手解决&#xff08;比如缺少合适的索引&#xff09;&#xff0c;有的需要尽快反馈给开发人员进行修改。 MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语…

搜集的一些有意思的牛人博客地址

我要去桂林-田春峰的IT网志 http://blog.donews.com/accesine/ SEO优化的内容 转载于:https://www.cnblogs.com/zhangweilong/archive/2012/11/19/2777719.html

memory拷贝与string拷贝的区别

1、memory拷贝&#xff0c;根据拷贝的字节个数&#xff0c;从src一个一个字节拷贝到dst&#xff0c;拷贝过程不管src的取值&#xff0c;也不管dst是否能容纳。2、因此&#xff0c;对于memory拷贝&#xff0c;src中NULL字符&#xff08;取值为0的字符&#xff09;后面的字符也能…

【转载】#323 - A Generic Class is a Template for a Class

A generic classs is a class that takes one or more type parameters, which it then uses in the definition of the class. It can be thought of as a template for a class. 1 public class ThingContainer<TParam> 2 { 3   private TParam theThing; 4 5   p…