http://blog.csdn.net/findaway123/article/details/6994203

2011

1.宏定义和函数的区别

-------------------------------------------------------------------------------------------------------------------

宏:宏定义是C提供的三种预处理功能的其中一种,这三种预处理包括:

(1)宏定义

(2)文件包含

(3)条件编译

1.不带参数的宏定义:

格式:#define 标识符 字符串

标示符就是可以替换字符串的宏名称,编译器在进行预处理过程中对使用宏替换的地方展开,用“字符串”替换宏名称,这样做的好处就是可以对数字或者随机数值指定一个有代表意义的名称,提高程序的可读性和通用性,在后期维护中可以方便的修改宏定义中字符串的数值大小或者其他数值类型,从而可以控制整个代码中所有引用宏名的地方。

从占用资源的角度看,编译器对宏替换不会占用或者分配内存,和函数比较,调用子函数需要分配内存,增加系统开销,但子函数可以把程序结构模块化,提高程序的可读性和聚合度,对比之下,宏也可以有参数,如果在程序中为了不调用子函数而减小开销,那么所有过程都写在一个函数中,并且没有自注释的名称,程序的可读性就会降低,毕竟代码是处理现实世界中事务数据关系的一种抽象,但不是一个人的,应该是像一首简洁,优美的诗,描述了美好的事务,所以折中之下,宏替换是个不错的选择。

虽然宏替换占用了编译器的时间,所谓“有得必有失”,减小了程序执行的资源消耗,这未尝不是一种平衡。

宏的一些特点(引用):

(1)宏名一般用大写

(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义 ,可以理解数组大小代表具体含义,便于二次维护。

(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。

(4)宏定义末尾不加分号;

(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。 (6)可以用#undef命令终止宏定义的作用域

(7)宏定义可以嵌套

(8)字符串" "中永远不包含宏

(9)宏定义不分配内存,变量定义分配内存。

带参数的宏:

格式: #define S(r) r*r

(1)实参如果是表达式容易出问题

area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;

正确的宏定义是#define S(r) ((r)*(r)) 。

(2)宏名和参数的括号间不能有空格

(3)宏替换只作替换,不做计算,不做表达式求解

(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存

(5)宏的哑实结合不存在类型,也没有类型转换。

(6)函数只有一个返回值,利用宏则可以设法得到多个值

(7)宏展开使源程序变长,函数调用不会

(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值。

(9):#define Uint unsigned int 即用 Uint 代替unsigned int 减小了书写的长度,还有就是不同操作系统的通用变量识别可以统一一致。

引用:宏定义其他冷门、重点知识(实际程序设计中也会用到)

(1) #define NAME "zhangyuncong"

程序中有"NAME"则,它会不会被替换呢?

(2) #define 0x abcd

可以吗?也就是说,可不可以用把标识符的字母替换成别的东西?

(3) #define NAME "zhang

这个可以吗?

(4) #define NAME "zhangyuncong"

程序中有上面的宏定义,并且,程序里有句:

NAMELIST这样,会不会被替换成"zhangyuncong"LIST

四个题答案都是否定的。

===================================================================

第一个,""内的东西不会被宏替换。这一点应该大都知道。

第二个,宏定义前面的那个必须是合法的用户标识符

第三个,宏定义也不是说后面东西随便写,不能把字符串的两个""拆开。

第四个:只替换标识符,不替换别的东西。NAMELIST整体是个标识符,而没有NAME标识符,所以不替换。

也就是说,这种情况下记住:#define 第一位置第二位置

(1) 不替换程序中字符串里的东西。

(2) 第一位置只能是合法的标识符(可以是关键字)

(3) 第二位置如果有字符串,必须把""配对。

(4) 只替换与第一位置完全相同的标识符 。

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

则遇到MAX(1+2,value)则会把它替换成:

((1+2)>(value)?(1+2):(value))

注意事项和无参宏差不多。

但还是应注意

#define FUN(a) "a"

则,输入FUN(345)会被替换成什么?

其实,如果这么写,无论宏的实参是什么,都不会影响其被替换成"a"的命运。

也就是说,""内的字符不被当成形参,即使它和一模一样。

那么,你会问了,我要是想让这里输入FUN(345)它就替换成"345"该怎么实现呢?

请看下面关于#的用法

3、 有参宏定义中#的用法

#define STR(str) #str

#用于把宏定义中的参数两端加上字符串的""

比如,这里STR(my#name)会被替换成"my#name"

一般由任意字符都可以做形参,但以下情况会出错:

STR())这样,编译器不会把“)”当成STR()的参数。

STR(,)同上,编译器不会把“,”当成STR的参数。

STR(A,B)如果实参过多,则编译器会把多余的参数舍去。(VC++2008为例)

STR((A,B))会被解读为实参为:(A,B),而不是被解读为两个实参,第一个是(A第二个是B)。

4、 有参宏定义中##的用法

#define WIDE(str) L##str

则会将形参str的前面加上L

比如:WIDE("abc")就会被替换成L"abc"

如果有#define FUN(a,b) vo##a##b()

那么FUN(id ma,in)会被替换成void main()

5、 多行宏定义:

#define doit(m,n) for(int i=0;i

{\

m+=i;\

}

其中有参宏定义中 #define  WIDE("abc")  L##str的用法,在高焕堂著作中《UML+OOPC 嵌入式开发精讲》中实现轻量级面向对象的方法中就使用了 ##的用法和多行宏定义用法。

所以根据上述特点使用好宏定义,可以写出优美的代码,防止程序中的不一致错误,提高可移植性,可读性,方便修改维护。只要所有引用宏定义的地方都可以做到一次修改就完成。

另外在很多源代码中有些宏就是函数名称。直接重新定义了函数的名称,增加了代码的可阅读程度。

条件编译:最开始可能也是出于提高程序设计的方便,对于源程序中某些内容只在特定条件下进行编译,于是乎条件编译就出现了,引用百科“一般情况下,源程序中所有的行都参加编译。但有时希望对其中一部分内容只在满足一定条件下才进行编译,即对一部分内容指定编译条件,这就是“条件编译”(conditional compile)。条件编译语句排版时,需考虑以下三种位置:1)条件编译语句块与函数定义体之间不存在相互嵌套(主要在(.h)文件中);2)条件编译语句块嵌套在函数体之外(主要在(.c)文件中);3)条件编译语句嵌套在函数体内

(主要在(.c)文件中)。条件编译指令将决定那些代码被编译,而哪些是不被编译的。可根据表达式的值或某个特定宏是否被定义来确定编译条件。”

控制开发可以是某个宏名是否被定义或者表达式的值来确定是否编译某部分代码。

引用:

文件包含命令的一般格式是:#include "文件名"或 #include

作用:预处理时,把“文件名”指定的文件内容复制到本文件,再对合并后的文件进行编译。

用途:避免重复劳动

说明:

1.双引号和尖引号的区别:双引号表示系统现在当前目录中寻找file所在的目录,若找不到,再按系统指定的

系统指定的标准方式寻找其它目录;尖引号仅查找按系统标准方式指定的目录.

2.一个#define只能指定一个包含文件,如 果要把多个文件都嵌入到源文件之中,则必须使用多个#define。

3.C语言允许嵌套使用#define。

在file1.c文件中,有文件包含命令#include "file2.c",预处理时,先把file2.c的内容复制到文件

file1.c,再对file1.c进行编译。

从理论上说,#include命令可以包含任何类型的文件,只要这些文件的内容被扩展后符合C语言语法。

2、被包含文件与其所在文件,在预处理后,成为一个文件,因此,如果被包含文件定义有全局变量,在其

它文件中不必用extern关键字声明。但一般不在被包含文件中定义变量。

c语言宏编译命令大全,C语言宏定义与预编译详解相关推荐

  1. java语言say方法,简单了解Java方法的定义和使用实现详解

    简单了解Java方法的定义和使用实现详解 发布时间:2020-09-25 11:36:07 来源:脚本之家 阅读:78 作者:OLIVER_QIN 这篇文章主要介绍了简单了解Java方法的定义和使用实 ...

  2. 【C语言】结构体定义 typedef struct 用法详解和用法小结

    结构体定义 typedef struct 用法详解和用法小结 文章目录 结构体定义 typedef struct 用法详解和用法小结 0. 前言 1. 首先:在C中定义一个结构体类型要用typedef ...

  3. c语言 recv_sin,C++_C语言中经socket接收数据的相关函数详解,recv()函数: 头文件:#incl - phpStudy...

    C语言中经socket接收数据的相关函数详解 recv()函数:头文件: #include #include 定义函数: int recv(int s, void *buf, int len, uns ...

  4. R语言使用survminer包生存分析及可视化(ggsurvplot)实战详解:从数据集导入、生存对象生成、ggsurvplot可视化参数配置、设置、可视化对比

    R语言使用survminer包生存分析及可视化(ggsurvplot)实战详解:从数据集导入.生存对象生成.ggsurvplot可视化参数配置.设置.可视化对比 目录 R语言使用survminer包生 ...

  5. 【转帖】windows命令行中java和javac、javap使用详解(java编译命令)

    windows命令行中java和javac.javap使用详解(java编译命令) 更新时间:2014年03月23日 11:53:15   作者:    我要评论 http://www.jb51.ne ...

  6. netcore 编译 html dll,ASP.NET Core Razor 视图预编译、动态编译

    0x01 前言 ASP.NET Core在默认发布情况下,会启动预编译将试图编译成xx.Views.dll,也许在视图中打算修改一处很细小的地方我们需要再重新编译视图进行发布.下面我将从 ASP.NE ...

  7. linux find文件,并复制,通过find命令寻找文件并拷贝到一个指定目录方法详解

    有这样的一个需求,需要将一部分符合条件的文件从一个目录拷贝到另一个目录中,可以通过使用find命令从源目录查找到符合条件的文件然后使用cp命令拷贝到目标目录 将通过find命令找到的文件拷贝到一个新的 ...

  8. 文本查找查找命令的grep 、egrep、fgrep用法的详解

    文本查找查找命令的grep .egrep.fgrep用法的详解 一.学习目标 了解并能熟悉运用grep.egrep.fgrep命令. 二.学习内容 1.grep.egrep.fgrep命令的意思和用法 ...

  9. linux 软链接 相对路径,Linux入门之ln命令创建软链接的绝对路径和相对路径详解(Ubuntu)...

    ln命令创建软链接的绝对路径和相对路径详解 简介 ln命令 总结 简介 Linux链接,可以分为硬链接与软链接:本文主要介绍软链接.(默认情况下,ln命令产生硬链接) 软链接文件类似于Windows的 ...

最新文章

  1. Eclipse中安装freemarker插件
  2. 智慧工厂如何运转?飞凌FCU2303-5G智能网关来告诉你
  3. h2 不能访问localhost_个人学习系列 - Spring Boot 整合 H2
  4. nth_element(a+1 , a + m, a + n+1);
  5. ai对话机器人实现方案_显然地引入了AI —无代码机器学习解决方案
  6. react 翻书效果_react实现页面切换动画效果
  7. 计算机语言学方面的期刊.,自然语言处理投稿哪些sci期刊
  8. 如何查看SSH key
  9. 物理专业计算机二级学科,学科门类二级类0702物理学类.doc
  10. 【DM】Combating Web Spam with TrustRank - 用TrustRank对抗网络垃圾邮件
  11. Android利用jsoup爬虫爬网页数据(一)
  12. php中的乐观锁和悲观锁
  13. 有意思的shell命令行提示符
  14. 微信小程序 canvas 笑脸
  15. Kafka topic分区增加副本
  16. 外行学计算机,《新手无忧学电脑:外行入门学电脑(2008至尊经典版)》低价购书_计算机与互联网_孔网...
  17. 查看网页上保存的密码-Google Chrome
  18. 95后的私密社交,在陌陌和探探上寻找“纯粹”
  19. 云服务器维护成本,云服务器维护成本
  20. 阿里程序媛凉安成长记:现世安稳,线上安稳

热门文章

  1. 【PHP 随记】—— ThinkPHP 配置数据库
  2. java中OOD_还在傻傻分不清?3分钟快速认识Java中的OOA、OOD、OOP
  3. 日处理200亿+调用,单机QPS高峰达到4万+,喜马拉雅自研 API 网关架构实践
  4. imgPreview 图片预览、国外网址
  5. Python 大仙:那个灯妖,那里逃?有没有健康码?非点证明?看仙器——泡泡圈, 1...2...3...4...
  6. 17. Nginx + keepalived 高可用
  7. 2021 hexo matery主题个性魔改
  8. U盘无法读取,不显示盘符
  9. mousewheel 取消_jquery mousewheel:检测车轮何时停止?
  10. mysql or不走索引分析