关于c语言预编译符号##的问题

hellochenhang 2009-03-09 03:08:36
如下简单的几行代码:

#include <stdio.h>
#include <stdlib.h>


#define MSGVAR( xx_level, xx_module,xx_fmt, ... ) \
do { \
printf( xx_module##": %s:%d: "##xx_fmt"\n", __FILE__, __LINE__, __VA_ARGS__ ); \
} while (0)

int main( int argc ,char* argv[] )
{
MSGVAR( 1, "xx", "%d,%d", 12,34);
}

在vs2005中能编译通过顺利运行,但是在linux下, gcc -o test test.c 却编译失败,失败的消息是:
test.c:12:1: error: pasting ""xx"" and "": %s:%d: "" does not give a valid
preprocessing token
test.c:12:1: error: pasting "": %s:%d: "" and ""%d,%d"" does not give a
valid preprocessing token
test.c:13:2: warning: no newline at end of file

于是我想是不是我用##语法用错了,所以我生成预处理文件分析一下,gcc test.c -E,输出结果:
int main( int argc ,char* argv[] )
{
test.c:12:1: error: pasting ""xx"" and "": %s:%d: "" does not give a valid
preprocessing token
test.c:12:1: error: pasting "": %s:%d: "" and ""%d,%d"" does not give a
valid preprocessing token
do { printf( "xx"": %s:%d: " "%d,%d""\n", "test.c", 12, 12,34 ); } while
(0);
test.c:13:2: warning: no newline at end of file
}

问题就出来了,我把test.c中用到了宏的那一行,用扩展以后的宏替换,
也就是把MSGVAR( 1, "xx", "%d,%d", 12,34);替换为:do { printf( "xx"": %s:%d: " "%d,%d""\n", "test.c", 12, 12,34 ); } while(0);
gcc -o test test.c ,ok直接通过。

有人能告诉我这是为什么吗。




...全文
1259 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
missedname 2009-03-09
  • 打赏
  • 举报
回复
让预编译时进行参数传递:"1"=>x,"2"=>y?
上面这段英文或许能解释吧~
traceless 2009-03-09
  • 打赏
  • 举报
回复
标记
missedname 2009-03-09
  • 打赏
  • 举报
回复
quote:
The token-pasting operator is only for making tokens - 'foo##bar'
becomes the single token 'foobar' and its result must always
produce a single valid token (or the results are undefined). Your
examples would have pasted a comma onto the begining of a
multichar token, and , is only a valid token by itself.
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 hellochenhang 的回复:]
我以前所理解的宏扩展就是文本替换,那么按照这种理解
#define CONCRETE(x,y) x##y
就应该能顺利连接两个字符串。
事实上,扩展开的代码可以编译,用宏却不能。

今天遇到的这个问题要让我重新更新一下对宏的认识了、
[/Quote]
问题似乎是这样的,gcc下不允许##后面出现符号,比如+-*/之类的,vc允许。。。。

#define M(M, N) M ## + N

这在vc下可以通过预处理并得到正确结果。。。。

http://gcc.gnu.org/onlinedocs/gcc-4.0.2/cpp.pdf
看这个。。。
feng4206yu 2009-03-09
  • 打赏
  • 举报
回复
只能做13楼的猜测了,楼主可以试验下...
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
我以前所理解的宏扩展就是文本替换,那么按照这种理解
#define CONCRETE(x,y) x##y
就应该能顺利连接两个字符串。
事实上,扩展开的代码可以编译,用宏却不能。

今天遇到的这个问题要让我重新更新一下对宏的认识了、
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hellochenhang 的回复:]
printf("a""b");
是可以的
printf("a"##"b");
不行,必须用宏替换
#define CONCRETE(x,y) x##y
printf(CONCRETE("1","2"));
就如同你调用printf不能是用p##rintf。
[/Quote]
vc下可以,gcc下就不行

#include <cstdio>
#include <cstdlib>

#define PRINT(INFO) printf(INFO##" output\n")
#define _P(S) S##"2"

int main(int argc, char* argv[])
{
PRINT("hello");
printf(_P("1"));
return 0;
}

这个在vc下可以通过预处理和编译
  • 打赏
  • 举报
回复
gcc下,似乎不能直接和字符串做##连接
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
printf("a""b");
是可以的
printf("a"##"b");
不行,必须用宏替换
#define CONCRETE(x,y) x##y
printf(CONCRETE("1","2"));
就如同你调用printf不能是用p##rintf。
  • 打赏
  • 举报
回复
我看你只有把##都去掉了,似乎只能这样
  • 打赏
  • 举报
回复
不对,刚才试了下
printf("a""b");这样的都可以,但是换成宏就不行
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
为什么字符串直接连接可以,vs2005里面用##连接也可以,gcc里面就不能用##
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jimmy_w 的回复:]
C/C++ code

#include <stdio.h>
#include <stdlib.h>


#define MSGVAR( xx_level, xx_module,xx_fmt, ... ) \
do { \
printf( #xx_module": %s:%d: "#xx_fmt"\n", __FILE__, __LINE__, __VA_ARGS__ ); \
} while (0)

int main( int argc ,char* argv[] )
{
MSGVAR( 1, xx, "%d,%d", 12,34);
system("pause");
return 0;
}




连接字符串不是用##,而是在宏变量前面加#
[/Quote]


明白你的意思,我输入的时候xx_module,xx_fmt就已经是字符串了,我只是想把这些组合成一个大的格式化字符串,传给printf。
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
问题的核心在,##连接字符串的时候出现问题,但是如果不用##,则没有问题,printf("1""2");是没错的,可是
#define CONCRETE(x,y) x##y

printf(CONCRETE("1","2"));则出错。
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <stdlib.h>


#define MSGVAR( xx_level, xx_module,xx_fmt, ... ) \
do { \
printf( #xx_module": %s:%d: "#xx_fmt"\n", __FILE__, __LINE__, __VA_ARGS__ ); \
} while (0)

int main( int argc ,char* argv[] )
{
MSGVAR( 1, xx, "%d,%d", 12,34);
system("pause");
return 0;
}


连接字符串不是用##,而是在宏变量前面加#
chenyingshu 2009-03-09
  • 打赏
  • 举报
回复
帮顶一下,我觉得跟编译器是有点关系的
zhirom 2009-03-09
  • 打赏
  • 举报
回复
平台问题,具体不知道,帮up
  • 打赏
  • 举报
回复
帮顶下
hellochenhang 2009-03-09
  • 打赏
  • 举报
回复
终于有人回应了,gcc版本没有问题,是4.1.2的,可变参数宏__VA_ARGS__ 可以用,但是就是在用##连接字符串的时候出问题。
充电宝111 2009-03-09
  • 打赏
  • 举报
回复
跟你的gcc版本有关系吧,不是所有的编译器都支持可变参数宏的__VA_ARGS__

70,024

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧