c语言宏高级用法,C语言宏高级用法 [总结]

1、前言

今天看代码时候,遇到一些宏,之前没有见过,感觉挺新鲜。如是上网google一下,顺便总结一下,方便以后学习和运用。C语言程序中广泛的使用宏定义,采用关键字define进行定义,宏只是一种简单的字符串替换,根据是否带参数分为无参和带参。宏的简单应用很容易掌握,今天主要总结一下宏的特殊符号及惯用法。

(1)宏中包含特殊符号:#、##.

(2)宏定义用do{ }while(0)

2、特殊符号#、##

(1)#

When you put a # before an argument in a preprocessormacro, the preprocessor turns that argument into a character array.

在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组

简化理解:#是“字符串化”的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串

#define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")

ERROR_LOG("add"); 转换为 fprintf(stderr,"error: "add"\n");

ERROR_LOG(devied =0); 转换为 fprintf(stderr,"error: devied=0\n");

(2)##

“##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。

在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些##来替代空格。

1 #define TYPE1(type,name) type name_##type##_type

2 #define TYPE2(type,name) type name##_##type##_type

TYPE1(int, c); 转换为:int  name_int_type ;(因为##号将后面分为 name_ 、type 、 _type三组,替换后强制连接)

TYPE2(int, d);转换为: int  d_int_type ;(因为##号将后面分为 name、_、type 、_type四组,替换后强制连接)

3、宏定义中do{ }while(0)

第一眼看到这样的宏时,觉得非常奇怪,为什么要用do……while(0)把宏定义的多条语句括起来?非常想知道这样定义宏的好处是什么,于是google、百度一下了。

采用这种方式是为了防范在使用宏过程中出现错误,主要有如下几点:

(1)空的宏定义避免warning:

#define foo() do{}while(0)

(2)存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。

(3)如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现:

#define foo(x) \

action1(); \

action2();

在以下情况下:

if(NULL == pPointer)

foo();

就会出现action1和action2不会同时被执行的情况,而这显然不是程序设计的目的。

(4)以上的第3种情况用单独的{}也可以实现,但是为什么一定要一个do{}while(0)呢,看以下代码:

#define switch(x,y) {int tmp; tmp="x";x=y;y=tmp;}

if(x>y)

switch(x,y);

else       //error, parse error before else

otheraction();

在把宏引入代码中,会多出一个分号,从而会报错。这对这一点,可以将if和else语句用{}括起来,可以避免分号错误。

使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低

4、测试程序

简单写个测试程序,加强练习,熟悉一下宏的高级用法。

fz.gif

1 #include

2

3 #define PRINT1(a,b) 4 { 5 printf("print a\n"); 6 printf("print b\n"); 7 }

8

9 #define PRINT2(a, b) 10 do{ 11 printf("print a\n"); 12 printf("print b\n"); 13 }while(0)

14

15 #define PRINT(a) 16 do{17 printf("%s: %d\n",#a,a);18 printf("%d: %d\n",a,a);19 }while(0)

20

21 #define TYPE1(type,name) type name_##type##_type

22 #define TYPE2(type,name) type name##_##type##_type

23

24 #define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")

25

26 main()

27 {

28 int a = 20;

29 int b = 19;

30 TYPE1(int, c);

31 ERROR_LOG("add");

32 name_int_type =a;

33 TYPE2(int, d);

34 d_int_type =a;

35

36 PRINT(a);

37 if (a >b)

38 {

39 PRINT1(a, b);

40 }

41 else

42 {

43 PRINT2(a, b);

44 }

45 return 0;

46 }

fz.gif

测试结果如下:

a42d980c5808ca04c2f4286d434ae0f2.png

5、参考网址

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

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

相关文章

Win 11 真的要来了!微软宣布 Win10 将于 2025 年终止支持!

微软今日正式更新支持页面,Windows 10 家庭版和专业版的支持将于 2025 年 10 月 14 日结束。值得注意的是,这是微软首次描述对 Windows 10 的支持结束,在此之前,微软仅记录了特定的 Windows 10 正式版本(如最新的 Wind…

每日一笑 | 为什么椅子总是最乱的?

全世界只有3.14 % 的人关注了数据与算法之美(图片来源于网络,侵权删)

js 操作cookies 方法

js 操作cookies 方法var str""; //JS操作cookies方法! //Expires 设置Cookie的有效期限 //Domain 添加域名限制 //Path 添加路径限制 //写cookies function setCookie(name,value){var Days30;//过期时间30天var datenew Date(); date.setTime(date.getTime()Day…

51单片机除c语言 中断嵌套,关于51系列单片机中断嵌套 - 关于单片机中断嵌套总结...

关于51系列单片机中断嵌套说最基本的,老的51单片机(80C51系列)有5个中断源,2个优先级,可以实现二级中断服务嵌套。现在很多扩展的51单片机已经有4个优先级(或更多)和更多的中断源了。在说到中断之前,我先来定义一下优先级&#xf…

R,让你的数据分析更简便!

R语言被广泛应用于生物、医学、电商、新闻等数据相关行业,是目前主流数据应用软件之一。它是用来进行统计分析、绘图和统计编程的强大工具,它在大规模的数据挖掘、可视化和报告方面已经取得了巨大的成功。你能够轻松地获取各种的包(通过 CRAN…

NET问答: 如何实现读写 file 的时候不用锁模式 ?

咨询区 Homam:我先说一下我的顾虑,是这样的,我有一个 windows service 服务在不断的写入日志,同时我还有个看板程序在不断的获取 windows service 程序写入的日志。问题是:service 程序在写日志的时候会 lock 文件&…

c语言基类型,C语言基本类型边界值

以int为例,不同电脑int位数不同,以64位电脑为例,int占4字节,及 4*8 32位bit,int 是带有符号的整形,所以第一位表示符号,则int边界值为 2^31 - 1。其他类型参考代码:#include #inclu…

久坐伤腰!这款德国3D美臀坐垫,分散身体压力,保护腰椎尾椎。

▲数据汪特别推荐点击上图进入玩酷屋一直听闻德国是一个「直肠子」国家他们的严谨、认真、一丝不苟让这个只有8000万人口的国家竟有2300多个享誉全球的名牌小到牙刷牙线,大到汽车「德国制造」已成为高品质的代名词德国品质到底是一种怎样的存在?德国人生…

C sharp实例:华盾武器门数据接收和解析

项目介绍:本实例主要是接收安检金属门的数据解析并显示到界面上,只做功能实现,不做界面美化硬件:金属门一个、网线一根、电脑主机,金属门网线可以直接接到电脑主机上开发环境:vs2017 系统:win10…

python 中文处理

python里面要处理中文,在模块首行加上以下:(注意要写在第一行,各种注释和import前面) #-*-coding:utf-8-*- 转载于:https://www.cnblogs.com/peterpanzsy/archive/2013/03/31/2992251.html

Nature封面:大团队日趋中庸,小团队更容易出颠覆性创新

全世界只有3.14 % 的人关注了数据与算法之美【导读】现代科学研究团队的规模越来越大,一般认为,大团队往往有着更充足的经费支持和多样化的研究人员,更有利于科学创新。但近日Nature发表封面文章,认为大团队往往因为失败代价太高而…

开源FastGithub

0 前言github网站访问慢或访问不了,相信很多人都会遇到过,解决方式大概有两种:一种是使用代理访问;另一种是使用ipaddress.com等域名解析网站查询域名的ip,然后在host文件增加ip与域名的映射。1 代理访问代理访问是在一…

linux 创建ll,两台linux建立GRE隧道

1.拓扑图: 备注:因为应用原因,需要在linux2上添加一个公网地址,并且在中间路由设备不受控制的情况下,Linux1能访问到linux2上面的公网地址。2.基本接口配置:linux1:192.168.10.1/24linux2:192.168.20.2/24R…

Exchange Server2010系列之十一:部署CAS+HT角色高可用性

Exchange Server 2010使用基于角色的管理模型。多角色服务器的安装及配置,我们在前面的文章中已经做过介绍。本案例中根据高可用性要求,我们需要把服务器角色部署在分开的服务器上面,并且实现CAS、HT、MBX角色的高可用。在此,我的…

用BenchmarkDotNet看Property

属性——Property,由get,set访问器组成,这是C#使用度比较高的类成员。今天分几组对比测试,来看一下使用Property的性能。被测试对象:public class MyClass {private string _myProperty1 DateTime.Now.ToString();public string …

盘点2019年最有钱的爸爸们

全世界只有3.14 % 的人关注了数据与算法之美纽约时间3月5日,又到了一年一度的大佬炫富时间了,福布斯发布第33期2019年度全球亿万富豪榜,全世界最有钱的人都在这了。第33期福布斯全球亿万富豪榜TOP20 ↓据统计,本次评选一共有2153位…

android拖拽 字体变形,字体变形的几种方法与技巧

原标题:字体变形的几种方法与技巧替换法是在统一形态的文字元素加入另类不同的图形元素或文字元素。 其本质是根据文字的内容意思,用某一形象替代字体的某个部分或某一笔画,这些形象或写实或夸张。将文字的局部替换,是文字的内涵外…

ML.NET Cookbook:(18)如何在文本数据上训练模型?

一般来说,所有的ML.NET学习器都希望这些特征是一个浮点向量。因此,如果您的一些数据不是一个float,您需要将其转换为float。如果我们想学习文本数据,我们需要从文本中“提取特征”。NLP(自然语言处理)的整个…

每日一笑 | 终于知道为什么胖了之后气质会垮了

全世界只有3.14 % 的人关注了数据与算法之美(图片来源于网络,侵权删)

android led闪烁功能,如何在Android应用层中制作一个LED指示灯效果

如何在Android应用层中制作一个LED指示灯效果发布时间:2020-12-08 16:12:59来源:亿速云阅读:86作者:Leah本篇文章给大家分享的是有关如何在Android应用层中制作一个LED指示灯效果,小编觉得挺实用的,因此分享…