关于宏##的使用注意一点
2014-12-12 08:39
211 查看
原文:关于宏##的使用注意一点在看《C语言高级编程》时,里面有个关于宏##的题目:
然后我实际动手测试了一下,先来第一种:
结果:
第一个答案其实预编译后给出的结果是不完全符合要求的。
然后是第二种:
首先,为什么要定义两个宏,一个不能解决问题吗?是的,不能。为什么?看这个链接:[短小精悍的宏](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?
果然给出了结果: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,但是这是一个未预定义的字符串,所以产生了一个未定义的行为。我们再看一个例子:
这个时候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)
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)
相关文章推荐
- 关于宏##的使用注意一点
- 关于宏##的使用注意一点
- 关于宏##的使用注意一点
- 关于Spring的HibernateTemplate的findByExample方法使用时的一点注意。
- 关于junit使用上的一点注意
- 关于strncpy和strcat组合使用时,需注意的一点问题
- 关于Java开发中使用Oracle数据库的一点注意事项
- 关于使用Carbide编译及配置的一点注意事项
- delphi中使用API时的一点注意之处
- 关于在applet中使用JDBC访问数据库的一点总结
- 关于使用Net2.0对AD编程的一点疑问?
- 关于使用ISCSI storage 的一点经验(完善中) 推荐
- 关于三层结构的一点使用心得与开发建议
- 关于浮点一点想法和使用
- 关于使用TestDriven.Net 2.0的一点补充
- 关于memset使用的一点小插曲
- 关于使用sping MVC框架进行文件上传的一点感受
- 关于fopen函数中路径名使用字符串的一点看法
- 关于三层结构的一点使用心得与开发建议
- 在WEB程序中使用.NET Remoting的IpcChannel时注意事项(关于“拒绝访问”问题的解决)