我看到这个有趣的问题here询问没有main()
的程序的可能性。在那里,我看到eon给出了一个如下答案,这在C / C ++中很有效。
#include<stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)
int begin()
{
printf(" hello ");
}
有人可以解释上面的代码是如何工作的吗?这里真的没有main()
或只是隐藏在我们的眼睛里吗?
答案 0 :(得分:10)
仔细查看宏:它只是将main
中的字符拼接到animate
并将其替换为begin()
。
答案 1 :(得分:4)
宏替换之后:
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)
begin
变为decode(a,n,i,m,a,t,e)
,然后变为main
。你有它。
答案 2 :(得分:2)
编译器看不到任何“开始”。它完全被它到编译器的时间所取代,因为宏只是文本替换。也许是一个有用的图表,可以添加其他很棒的答案。
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)
查看m
,查看参数列表中m
的位置。
decode(s,t,u,m,p,e,d)
^
|
decode(a,n,i,m,a,t,e)
因此第一个字母是m => m
。然后重复此过程s => a
,u => i
,t => n
。
decode(s,t,u,m,p,e,d)
^ ^ ^
| | |
decode(a,n,i,m,a,t,e)
然后生成的字母与token concatenation一起“粘贴”,就编译器而言,它看起来像main
。
答案 3 :(得分:1)
这是因为编译器没有真正看到int begin(){}
,在执行宏替换和连接运算符之后,预处理器将用begin
替换main
。
首先预处理器会将begin
替换为decode(a,n,i,m,a,t,e)
,之后它会在替换列表上进行重新扫描以进一步替换,它会找到类似函数的宏decode
在执行连接运算符后替换为它的替换列表,如下所示:
m##a##i##n => main
因此,编译器只会看到包含int main(){}
而不是int begin(){}
的预处理器输出,因此是合法代码。