在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。
 
  首先,函数调用会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。这种开销不仅会降低代码效率,而且代码量也会大大增加,而使用宏定义则在代码规模和速度方面都比函数更胜一筹;其次,函数的参数必须被声明为一种特定的类型,所以它只能在类型合适的表达式上使用,我们如果要比较两个浮点型的大小,就不得不再写一个专门针对浮点型的比较函数。反之,上面的那个宏定义可以用于整形、长整形、单浮点型、双浮点型以及其他任何可以用“>”操作符比较值大小的类型,也就是说,宏是与类型无关的。

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

下面一段代码的功能是显示C整数类型的长度和范围:

#include<stdio.h>
#define RANGE(type, name)                         \{                                                \type minval,maxval,bit;                         \unsigned bits;                                  \char *format;                                   \\/*Measure size of data type in bits*/           \bits=1;bit=(type)1;while(bit<<=1)bits++;        \/*signed or unsigned?*/                         \if ((type)(1L<<(bits-1))>0)                    \{                                             \format="%12lu";/*unsigned*/                   \minval=(type)0;                               \}                                             \else                                          \{                                             \format="%12ld";/*signed*/                     \minval=(type)1<<(bits-1);                     \}                                             \\maxval=minval-1;/*roll over backwards!*/      \\printf("%20s(%2u bits):",name,bits);          \printf(format,(long)minval);                   \printf("to");                                  \printf(format,(long)maxval);                   \printf("\n");                                  \}                     int main(){printf("\nTesting range of UNSIGNED ints...\n\n");RANGE(unsigned char,"unsigned char");RANGE(unsigned short int,"unsigned short int");RANGE(unsigned int,"unsigned int");RANGE(unsigned long int,"unsigned long int");printf("\nTesting range of SIGNED ints...\n\n");RANGE(signed char,"signed char");RANGE(signed short int,"signed short int");RANGE(signed int,"signed int");RANGE(signed long int,"signed long int");printf("\n");return 0;}

程序运行结果如下:

说明:

1、使用#define声明多行宏函数与声明单行宏函数没有本质区别;
  2、多行声明时,回车换行前要加上字符‘\’,即“\[enter]”,注意字符‘\’后要紧跟回车键,中间不能有空格或其他字符。
  3、另外,在Linux操作系统中 “\[enter]”称为跳脱字符,意思是一行写不完的时候可以使用跳脱字符换行,但对于操作系统而言,它认为你并没有换行。

如何用#define宏定义多行函数相关推荐

  1. #define宏定义形式的函数导致的bug

    定义了一个宏定义形式的"函数": #define  SUM8(YY)\ {\ int Y = YY>>2;\ ...\ } 然后使用的时候,传入了一个同名的变量Y: i ...

  2. C语言基础知识之define宏定义表达式,undef,内存对齐,a和a的区别,数组知识点,int (*)[10] p,二维数组参数与二维指针参数,函数指针数组,常见的内存错误及对策

    一.用define宏定义表达式 1.定义一年有多少秒: #define SEC_A_YEAR 60*60*24*365 //上述描述不可靠,没有考虑到在16位系统下把这样一个数赋给整型变量的时候可能会 ...

  3. 关于C语言刷题(#define宏定义函数的常见错误)

    关于C语言刷题(#define宏定义函数的常见错误) 首先我们来先看对#define的定义 define,宏定义,C语言中预处理命令一种.分为无参宏定义和带参宏定义.无参宏定义的一般形式为:#defi ...

  4. #define宏定义是什么?怎么写?一文搞懂。

    前言 第一次接触宏定义的时候,是在学校的C++课程大作业中.当时有幸看到了大佬写的源码,里面有很多的宏定义.当时并不了解宏定义的妙用,只感觉它像是定义了一个变量一样,不好理解还有些多此一举. 这之后在 ...

  5. 函数式宏定义与普通函数的区别?C语言宏定义和宏定义函数 ?

    http://www.jb51.net/article/41869.htm 尽管函数式宏定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧.传参.传返回 ...

  6. C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  7. 用宏定义代替printf函数

    问题提出 有时候我们想用宏定义来决定是编译debug版本的代码还是release的代码,dubug版本的代码会通过printf打印调试信息,release版本的代码则不会.我们总不能对每一条print ...

  8. define宏定义中的#,##,@#及\符号

    define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (string ...

  9. c语言数组宏定义标识符,C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针...

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

最新文章

  1. 图文解说nginx中server的匹配顺序
  2. Android -- 带你从源码角度领悟Dagger2入门到放弃(三)
  3. 正则表达式 学习笔记5.3
  4. mybaits二十八:逆向工程
  5. 百度商桥修改服务器,百度商桥 · 响应式网站编辑器使用手册 · 看云
  6. 红帽linux更新指令,CentOS7.0命令更新新版特性详解
  7. 对现有的所能找到的DDOS代码(攻击模块)做出一次分析----UDP篇
  8. 历久弥新 - 微软万亿市值背后的文化支撑(上)|DevOps案例研究
  9. JAVA入门级教学之(数据转换规则)
  10. 【Python】Turtle绘制科赫雪花
  11. dw怎么修改html框架的宽度,Dreamweaver (dw)cs6中div标签宽度和高度设置方法
  12. 网络爬虫基本原理(二)
  13. 如何查看电脑上是否安装有IIS服务
  14. 吴恩达机器学习编程题ex1上 单变量线性回归: (python版含题目要求、代码、注解)
  15. Windows 9预览版今秋发布 正式版明年推出
  16. Java double value_Java Double doubleValue()用法及代码示例
  17. matlab差值后求斜率,用三次样条插值求离散点斜率 matlab程序
  18. 益智java单词游戏_java实现单词搜索迷宫游戏
  19. html网页中圆角边框的编写,Html实现边框圆角的实例详解
  20. 快速了解K4B2G1646F-BYK0

热门文章

  1. Openstack nova-scheduler 源码分析 — Filters/Weighting
  2. STM32 中JTAG 引脚作为普通IO口设置方法
  3. 探索移动端的搜索设计
  4. 线程安全的无锁RingBuffer的实现
  5. Sorting It All Out--POJ 1094
  6. Linux 下 PHP 5.2.x 连接 SQL Server 数据库 FreeTDS 配置笔记
  7. jquery gridly (拖拽插件)
  8. zabbix监控windows主机
  9. Docker之HelloWorld篇
  10. 安装高可用性虚拟机,livemigration系列之九