关于宏##的使用注意一点

原文:关于宏##的使用注意一点

在看《C语言高级编程》时,里面有个关于宏##的题目:

1.已知#define A “menu”
#define B “osd”,
若请使用宏A,B表示出字符串”menuosd”

答案:1 答案1:#define C A B
答案2:#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

 

然后我实际动手测试了一下,先来第一种:

#include <stdio.h>
#define A "menu"
#define B "osd"
#define STR A B

int main(int argc, char *argv[])
{
char *p = STR;
return 0;
}
gcc -E hell.c -o hello.i
cat hello.i

结果:

int main(int argc, char *argv[])
{

char *p = "menu" "osd";

return 0;
}

 

第一个答案其实预编译后给出的结果是不完全符合要求的。

然后是第二种:

#include <stdio.h>
#define A "menu"
#define B "osd"

#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

int main(int argc, char *argv[])
{
char *p = C(A,B);
printf("%s\n", p);
return 0;
}

 

首先,为什么要定义两个宏,一个不能解决问题吗?是的,不能。为什么?看这个链接:[短小精悍的宏](http://www.cnblogs.com/wb-DarkHorse/archive/2013/04/27/3046749.html)
然后再次按照上边的命令进行预编译,但是给出了错误信息:pasting "menu" and "osd" does not give a valid preprocessing token gcc
这就奇怪了。然后google了一下,发现了相同的问题:
[问题](http://stackoverflow.com/questions/4667779/preprocessor-macro-gcc-pasting-x-and-x-does-not-give-a-valid-preprocessing-toke)

并且里面说了,这种情况在VS里面不会报错,可以直接工作。so?

#include <stdio.h>
#define A "menu"
#define B "osd"

#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

int _tmain(int argc, _TCHAR* argv[])
{
char *p = C(A,B);//STR;
printf("%s\n", p);
return 0;
}

 

果然给出了结果:menuosd

为什么gcc和VS会对这个问题给出差异的结果呢?看这个问题:
[that's why](http://stackoverflow.com/questions/1206624/differences-in-macro-concatenation-operator-between-visual-c-and-gcc?rq=1)

根据C标准,用##操作后的结果必须是一个已经预定义过的符号。否则是未定义的。所以gcc和vs对于这个未定义行为表示了不同的看法,前者是给出错误,后者一笑而过。那什么是已经预定过的符号呢? 它包含了这些:头文件名, 等式, 预处理数字, 字符常数, 字符串值, 标点符号, 单个非空字符

在我们的例子中,_C_(a,b)用##连接后,应该是产生menuosd,但是这是一个未预定义的字符串,所以产生了一个未定义的行为。我们再看一个例子:

#define A 2
#define _CONS(a,b) (a##e##b)
#define CONS(a,b) _CONS(a,b)

int main(int argc, char *argv[])
{
printf("%f\n", CONS(A, A));
return 0;
}

 

这个时候gcc不会给出错误提示了。结果:200.0000
为什么这个时候不给出错误提示呢?我的理解是,CONS(A, A)替换后成为2e2,而这时一个常量,符合C标准。

ok,给出一个链接,详细的解释了gcc中##的用法:
[gcc concatenation](http://gcc.gnu.org/onlinedocs/gcc-4.3.3/cpp/Concatenation.html#Concatenation)

 

 

时间: 2025-01-29 08:15:27

关于宏##的使用注意一点的相关文章

搞全闪存阵列的各执一词 宏杉说别吵了,就用我哒

全闪存阵列也许十分诱人,但并不是每一个全部使用闪存介质的存储阵列,都称得上"纯粹的全闪存阵列",它们中的许多,并不完美. "尺有所长,寸有所短",在企业级存储市场,产品指标上略有不同,产品特性上各有所长,本是再常见不过的事情,但是在"全闪存阵列到底为什么'不完美'?"这个命题上,站在不同角度的存储系统供应商,"吵架"吵的也是颇有水准. 过去十几年在市场上获得显著成功的大厂们认为,"那些初创企业的产品并不完美,它们太像

李彦宏:中国互联网格局未确定 帮助企业是大戏

在李彦宏看来,中国互联网格局远远没有确定."中国互联网经过十几年的发展,很多人可能觉得大局已定,"李彦宏近日对记者表示,"这个判断跟我的判断是不一样的."李彦宏认为,中国互联网大幕才刚刚拉开,好戏还在后头. 李彦宏表示,中国互联网发展出了很多成功的公司.但过去十几年发展最好的这些公司,基本上都在是跟用户个人消费相关的产业,比如短信.网游和即时通讯. 目前,腾讯依靠即时通讯为核心所构建的互联网增值服务模式占据了龙头地位.而网游企业也是 纳斯达克市场上数量最为庞大的&q

百度股价4个月上涨80%李彦宏称好戏在后头

700美元,百度站稳中国互联网第二 李彦宏:好戏在后头 孙进 在几天前因一季度财报利好而冲上700美元/股的搜索引擎百度(BIDU.NASDAQ)股价可能"昙花一现"--因为其将在12日按照10:1的比例执行拆股计划,以加强股票的流通性,从而给中国互联网留下一个最高股价的短暂纪录. 不过,百度将站稳中国互联网市值第二的位置.以4日收盘价计算,腾讯(00700.HK)以约390亿美元市值位列第一,百度247亿美元为第二,阿里巴巴约98亿美元为第三,携程.网易和盛大网络等跟随,但市值都在5

乌镇峰会启幕李彦宏移动转型成功经验受关注

首届世界互联网大会(乌镇峰会)将于明天正式开幕,海内外互联网领军人物云集江南水乡--乌镇,中国互联网发展理念和阶段成果将在大会上得到全面展示.当下,移动转型成为每一家互联网企业定义未来的重心.李彦宏领衔的百度,在今年第三季度实现移动端流量反超PC,移动营收占比达到36%,领跑BAT(阿里22%.腾讯18.9%),移动营收近49亿,也大幅领先于竞争对手(阿里腾讯都在35亿左右),在中国乃至全球范围内,都是移动转型非常成功的互联网企业,成为此次互联网大会参会者.媒体及行业的关注焦点."这几年,每一家

百度朱光:3点前删除干净所有侵权作品

张京科 丁婷婷 杜江"抱歉"效果不给力,百度昨日祭出危机公关"2.0版"."明天 下午3点前,所 有的百度文学侵权类作品一定会删除干净."昨晚,百度副总裁朱光对<第一财经日报>记者表示.同一天,百度董事长兼CEO李彦宏首次谈及百度文库问题.他在当天举行的2011中国(深圳)IT领袖峰会上表示:"管得好就继续管,管不好就关掉."但对于这一表态,外界似乎仍不买账.一些人士在接受记者采访时给出了"场面话&quo

深圳论剑,互联网大佬同台对话

和讯网消息 3月25日,2012中国(深圳)IT领袖峰会于3月24-25日在深圳五洲宾馆举行,本届峰会主题为"转型中的谋略之道".作为本届峰会的全程战略合作伙伴,和讯网将对大会进行全程网络直播. 25日下午,在"蝙蝠群侠网天下"的高端对话中,北京航空航天大学校长怀进鹏.百度董事长李彦宏.腾讯董事会主席马化腾同台高峰对话. 现场文字实录: 吴鹰:我想我们从这次整个IT领袖峰会主论坛转型中的谋略之道到我们今天这个对话论坛,我的任务很艰巨,我们上午高端对话论坛是我们美女宋

【可视化】图表展示中的10个经典问题

一直想写这样一本介绍数据可视化的书.可以介绍一些日常办公中常常用到的图表处理的技巧并且能够推荐给读者一些非常优秀的小工具,比如Xcelsius.Smartdraw.Visio.Swiff Chart.ColorWheel.Tableau.Ucinet.Excel.PPT.Mindmanager等等. 几乎所有的报告都离不开数据图表的应用,但是在图表应用的过程中似乎往往会遇到各种各样的问题.比如词不达意.数据与图形步匹配.图表配色不协调等等.所以我也想能够通过这样一本书抛砖引玉,为图表的制作提供参

c++中枚举常量与宏常量的一点区别

  #include<iostream> using namespace std; class A { enum { APPLE = 111 }; #define PEAR 333 public: A() { cout << "APPLE: " << APPLE << endl; // 私有枚举常量,只有在类内部可以访问. } }; int main() { A a; //cout << "APPLE: "

宏定义的黑魔法 - 宏菜鸟起飞手册

宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加.如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD).但是因为宏定义对于很多人来说,并不像业务逻辑那样是每天会接触的东西.即使是能偶尔使