#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
只需通过查看程序,"可能"期望输出,对于两个printf语句都是相同的.但是在运行程序时,你得到它:
bash$ ./a.out
12
f(1,2)
bash$
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
AFAIK,这个问题同样适用于C和C++
C标准中规定的"翻译阶段"的第6步(C99标准草案中的5.1.1.2)规定,必须将相邻的字符串文字连接成单个文字.即
printf("helloworld.c" ": %d: Hello "
"world\n", 10);
Run Code Online (Sandbox Code Playgroud)
等同于(语法上):
printf("helloworld.c: %d: Hello world\n", 10);
Run Code Online (Sandbox Code Playgroud)
但是,标准似乎没有指定编译器的哪个部分必须处理它 - 它应该是预处理器(cpp)还是编译器本身.一些在线研究告诉我,这个函数通常应该由预处理器(源#1,源#2,还有更多)执行,这是有道理的.
但是,cpp在Linux中运行显示cpp不执行此操作:
eliben@eliben-desktop:~/test$ cat cpptest.c
int a = 5;
"string 1" "string 2"
"string 3"
eliben@eliben-desktop:~/test$ cpp cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpptest.c"
int a = 5;
"string 1" "string 2"
"string 3"
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是:在预处理器或编译器本身中,应该在何处处理该语言的这一特性?
也许没有一个好的答案.基于经验,已知编译器和一般良好工程实践的启发式答案将不胜感激.
PS如果你想知道为什么我关心这个......我正在试图弄清楚我的基于Python的C语法分析器是否应该处理字符串文字连接(目前它没有这样做),或者将它留给cpp哪个它假设在它之前运行.
我正在尝试编写dbgassert类似于标准的宏assert。除了做什么以外assert,我还想dbgassert打印任意数量的其他参数(包含调试信息)。
下面列出了我到目前为止所拥有的,这是从SO答案改编而来的。但是我在代码中存在可变参数模板或宏的问题。如果我至少使用一个附加参数(“确定”行),则dbgassert可以按预期工作。但是,如果我不给出其他参数,则编译将失败(问题行)。
我在可变参数模板编程方面有一些经验(例如如何打印元组),但是我以前从未使用过可变参数宏。
能否请您解释编写这种可变参数宏组合的正确方法是什么?
顺便说一句,有人可以解释 #EX在宏中魔术吗?它显示了表达式并在gcc4.8.1上为我工作。它得到普遍支持吗?
谢谢,
码:
//corrected reserved identifier issue and assumption issues per comments
#include <cassert>
#include <iostream>
using namespace std;
template <typename ...Args>
void realdbgassert(const char *msg, const char *file, int line, Args ... args) {
cout << "Assertion failed! \nFile " << file << ", Line " << line << endl
<< " Expression: " << msg << endl;
std::abort();
}
#define …Run Code Online (Sandbox Code Playgroud) 方案一:
#include <stdio.h>
#define foo(x, y) #x #y
int main()
{
printf("%s\n", foo(k, l)); //prints kl
return 0;
}
Run Code Online (Sandbox Code Playgroud)
方案2:
#include <stdio.h>
#define foo(m, n) m ## n
int main()
{
printf("%s\n", foo(k, l)); //compiler error
}
Run Code Online (Sandbox Code Playgroud)
为什么两个程序的输出会有如此大的差异?这两个程序之间的确切区别是什么?