关于gcc扩展中的宏定义中用 # 和 ##

关于gcc扩展中的宏定义中用 "#" 和 "##"

今天测试了宏定义中的 "#" 和 "##" 的区别。

结果如下:

"#" 代表和一个字符串相连接

"##" 代表和一个符号连接,符号可以是变量,或另一个宏符号。

举例如下:

宏定义如下

(1)

#define DEV_FILE_NAME    "/dev/test_kft"

#define OPEN_FILE(fd, n)    /
{   /
    fd = open(DEV_FILE_NAME #n,O_RDONLY); /
    if(fd < 0) /
    { /
       printf("Open device error/n"); /
        return 0; /
    }   /
}

如此调用:

    OPEN_FILE(fd1, 1);
    OPEN_FILE(fd2, 2);
    OPEN_FILE(fd3, 3);
    OPEN_FILE(fd4, 4);
    OPEN_FILE(fd5, 5);
    OPEN_FILE(fd6, 6);

用gcc -E展开后,如下

2299:    { fd1 = open("/dev/test_kft" "1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:    { fd2 = open("/dev/test_kft" "2",00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:    { fd3 = open("/dev/test_kft" "3",00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:    { fd4 = open("/dev/test_kft" "4",00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:    { fd5 = open("/dev/test_kft" "5",00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:    { fd6 = open("/dev/test_kft" "6",00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

如果没有定义DEV_FILE_NAME ,就是

2299:    { fd1 = open(DEV_FILE_NAME "1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:    { fd2 = open(DEV_FILE_NAME "2",00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:    { fd3 = open(DEV_FILE_NAME "3",00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:    { fd4 = open(DEV_FILE_NAME "4",00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:    { fd5 = open(DEV_FILE_NAME "5",00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:    { fd6 = open(DEV_FILE_NAME "6",00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

所以可以很清楚的看出#n 解析出来的是"n" , 用于连接一个已有的字符串。

(2) 再来看 ## 是什么意思, 宏定义如下:

#define OPEN_FILE(fd, n)    /
{   /
    fd = open(DEV_FILE_NAME ##n,O_RDONLY); /
    if(fd < 0) /
    { /
       printf("Open device error/n"); /
        return 0; /
    }   /
}

调用方式相同。

看宏展开:

2299:    { fd1 = open(DEV_FILE_NAME1,00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:    { fd2 = open(DEV_FILE_NAME2,00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:    { fd3 = open(DEV_FILE_NAME3,00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:    { fd4 = open(DEV_FILE_NAME4,00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:    { fd5 = open(DEV_FILE_NAME5,00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:    { fd6 = open(DEV_FILE_NAME6,00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

现在看清楚了, ##n 的作用是把n直接连接在了一个符号的末尾. 好, 现在我们定义一个符号看看效果。

#define DEV_FILE_NAME1    "/dev/test_kft1"

再展开:


2299:    { fd1 = open("/dev/test_kft1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:    { fd2 = open(DEV_FILE_NAME2,00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:    { fd3 = open(DEV_FILE_NAME3,00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:    { fd4 = open(DEV_FILE_NAME4,00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:    { fd5 = open(DEV_FILE_NAME5,00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:    { fd6 = open(DEV_FILE_NAME6,00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

很显然第一个符号被替换了, 因为是符号是宏的缘故。 这样我们也能把这一扩展特性应用在变量上。


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

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

相关文章

java 年计算_java实现计算某年某月的天数

在计算某年某月的天数时&#xff0c;需要注意平年闰年。分析&#xff1a;闰年具体的判定方法就要看它的判定条件&#xff1a;四年一闰 &#xff0c; 百年不闰 &#xff0c;400年再闰。而计算该年该月的天数&#xff0c;又分大月和小月&#xff0c;特殊月份2月之分。(视频教程推…

添加自定义菜单,报错40155

2019独角兽企业重金招聘Python工程师标准>>> 提交的json中&#xff0c;某个自定义菜单对应的URL访问是有问题的&#xff0c;请挨个检查一下。 转载于:https://my.oschina.net/selly1025/blog/1551496

gcc编译流程及中间表示层RTL的探索

gcc编译流程及中间表示层RTL的探索收藏新一篇: 解读VC编程中的文件操作API和CFile类 | 旧一篇: Effective Item21 尽可能使用const 内容摘要 本文将以 C 语言为例&#xff0c;介绍 gcc 在接受一个 .c文件的输入之后&#xff0c;其前端是如何进行处理并得到一个中间表示并转交给…

【bzoj2132】圈地计划 网络流最小割

题目描述 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解&#xff0c;这块土地是一块矩形的区域&#xff0c;可以纵横划分为NM块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境&#xff0c;每…

python爬虫爬取数据如何将br去掉_Python怎么去除爬取下来的网站中的一些转义字符串 - 收获啦...

基本方法其实用python爬取网页很简单&#xff0c;只有简单的几句话这样就可以获得到页面的内容。接下来再用正则匹配去匹配所需要的内容就行了。但是&#xff0c;真正要做起来&#xff0c;就会有各种各样的细节问题。2.登录这是一个需要登录认证的网站。也不太难&#xff0c;只…

Linux基础

Linux的特点&#xff1a; 系统版本&#xff1a;常见的有debian、Redhat更适合做服务器&#xff0c;更安全和稳定&#xff0c;Ubuntu唯一的优势就是图形界面好&#xff0c;centos目前被redhat收购&#xff0c;红旗已经倒闭。 1、免费的/开源的&#xff1b;2、支持多线程/多用户&…

GCC的编译和调试--入门介绍

编译与调试1.1编译的概念和理解在进行C程序开发时&#xff0c;编译就是将编写的C语言代码变成可执行程序的过程&#xff0c;这一过程是由编译器来完成的。编译器就是完成程序编译工作的软件&#xff0c;在进行程序编译时完成了一系列复杂的过程。1.1.1程序编译的过程在执行这一…

A* a=new B ,会不会产生内存泄露了,露了B-A的部分?

A* anew B ,delete a;会不会产生内存泄露了&#xff0c;露了B-A的部分。其中B为A的子类 析构函数在下边3种情况时被调用&#xff1a;1.对象生命周期结束&#xff0c;被销毁时&#xff1b;2.delete指向对象的指针时&#xff0c;或delete指向对象的基类类型指针&#xff0c;而其基…

spring 第一天:1015

对象加强的三种方法&#xff1a;1/继承2/装饰着模式3/动态调用 2&#xff1a;装饰着模式&#xff1a;就是就是1-先建一个基类 &#xff0c;如咖啡类 。味道很苦2- 再建一个类配料类 也就是说是所欲配料种类的父类。然后写多配料子类个子类继承配料类&#xff0c;。3-子类三个步…

java public 继承_java继承问题

代码&#xff1a;父类&#xff1a;public class Father {public Father() {System.out.println("基类构造函数{");show();new a();System.out.println("}");}public void show() {System.out.println("基类----show");}public class a {public a…

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数(数位DP+恶心细节)

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 Time Limit: 5 Sec Memory Limit: 64 MBDescription 正如你所知&#xff0c;奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺序。她们甚至也不能通过仍硬币的方式。 所以她们通过"round number&q…

Optimizing Code with GCC

现在的编译器越来越聪明&#xff0c;功能越来越强&#xff0c;从简单的函数内联&#xff0c;到复杂的寄存器分析&#xff0c;一系列代码革命使程序运行得越来越快。大多数时候&#xff0c;更快比更小重要&#xff0c;因为磁盘空间和内存都变得便宜了。但是在嵌入式系统里&#…

QTP的那些事--操作excel的函数

1: QTP Excel函数 操作EXCEL 数据表格 表单 编辑EXCEL 工作表 2: Dim ExcelApp As Excel.Application 3: Dim excelSheet As Excel.worksheet 4: Dim excelBook As Excel.workbook 5: Dim fso As scrīpting.FileSystemObject 6: 7: ******************…

java-生产者消费者模式

经常会有公司叫我们手撕代码&#xff0c;比如网易&#xff0c;阿里&#xff0c;那我们是不是该掌握下呢。下面这段代码来自《现代操作系统》进程与线程P49页。 public class ProducerConsumer {public ProducerConsumer() { }private static final int N 100;static Producer …

yum查询已经安装mysql_通过yum安装mysql

在linux中安装数据库首选MySQL&#xff0c;Mysql数据库的第一个版本就是发行在Linux系统上&#xff0c;其他选择还可以有postgreSQL&#xff0c;oracle等在Linux上安装mysql数据库&#xff0c;我们可以去其官网上下载mysql数据库的rpm包&#xff0c;http://dev.mysql.com/downl…

koa2-cookie-session

node.js的path.extname方法使用   由于该方法属于path模块&#xff0c;使用前需要引入path模块&#xff08;var path require(“path”) &#xff09;   接收参数&#xff1a;   p path 路径 path.extname(index.html)// returns.htmlpath.extname(index.)// returns.pat…

从程序员角度看ELF

从程序员角度看ELF原文:《 ELF:From The Programmers Perspective》作者&#xff1a;Hongjiu Lu <mailto: hjlnynexst.com>NYNEX Science & Technology, Inc. 500 Westchester Avenue White Plains, NY 10604, USA 翻译&#xff1a;alert7 <mailto: alert721cn.co…

JAVA命令符找不到符号_[转]Java命令行编译文件时出现的错误,找不到符号或软件包不存在等...

标签(空格分隔)&#xff1a; Javajavascript习惯了eclipse的自动编译&#xff0c;Java命令行编译、执行文件只会最基础的部分&#xff0c;就是对单文件的编译和执行&#xff0c;并且不包含任何外部JAR包。但有时候你还非得用命令行&#xff0c;会碰到一些问题&#xff0c;博主这…

C#中POST数据和接收的几种方式

POST方式提交数据&#xff0c;一种众所周知的方式&#xff1a; html页面中使用form表单提交&#xff0c;接收方式&#xff0c;使用Request.Form[""]或Request.QueryString[""]来获取。 这里介绍另外一种POST方式和接收方式&#xff0c;就是将整个数据作为加…

java自动注入注解_Spring自动注解标签@Autowired不能注入xml配置的bean吗?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼配置service的xmlservice代码public class LoginServiceImpl extends BaseDaoServiceImpl implements LoginService {Overridepublic Map queryByUserName(String userName){IDao iDao super.getAppDao();return (Map)iDao.queryF…