关于宏##的使用注意一点
来源:互联网 发布:网络联盟论坛 编辑:程序博客网 时间:2024/06/12 22:17
转载自: 关于宏##的使用注意一点
在看《C语言高级编程》时,里面有个关于宏##的题目:
1.已知#define A “menu”
#define B “osd”,
若请使用宏A,B表示出字符串”menuosd”答案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 Bint 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;}
首先为什么要定义两个宏, 一个不能解决问题么? 是的, 不能. 为什么? 请看这个链接: 短小精悍的宏.
然后再次按照上边的命令进行预编译, 但是编译器给出了错误信息
pasting “menu” and “osd” does not give a valid preprocessing token gcc
这就奇怪了, 然后Google了一下, 发现了相同的问题: stackoverflow.com
并且里面说了, 这种情况在VS里是不会报错的, 可以直接工作.
#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
根据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
- 关于宏##的使用注意一点
- 关于宏##的使用注意一点
- 关于header()的一点注意
- 关于ASPxButton的一点注意
- 关于UnitySendMessage 的一点注意
- MSDN使用的一点注意
- 关于Hibernate配置的一点注意
- 关于accept函数需要注意的一点
- 关于connect需要注意的一点
- 关于COOKIES需要注意的一点
- 关于wget应用的一点注意。
- 关于printf的一点小注意
- 关于iOS通知的一点注意
- 关于strncpy和strcat组合使用时,需注意的一点问题
- 使用 FancyUpload需要注意的一点
- Qt中QMap的使用注意一点
- Qt中QMap的使用注意一点
- 使用GetWindowText需要注意的一点问题
- Codeforces 900D/E
- 版本时光机
- Codeforces Testing Round #14 (Unrated) A
- cs231n笔记(8+)——全连接层
- 远程版本库
- 关于宏##的使用注意一点
- 创建版本库
- 物体检测及分类方法总结(提供了很多论文和代码链接)
- MYSQL的Commit与程序的原子性
- clion_cmakelists收集
- 进程同步与进程互斥
- spring系列(四):切面编程(aop)2
- C#中WPF下自定义滚动条ScrollViewer样式
- error LNK2026