2015-11-05 80 views
0

我只是碰到这种奎因问题就来了,但没有人真正走进它是如何工作的:C/C++ program that prints its own source code as its output这个奎因是如何工作的?

char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);} 

我特别不明白的是以下具有即使我改变了整数相同的输出:

char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,5,s,11);} 

它仍然打印34s!有人能一步步走过我吗?

+0

它在'char * s ='之后和第二个'; main(){'之前打印什么?(引号应该是这样的) – immibis

+3

这与标题有什么关系? – user2357112

+0

'char * s =“blah”;'作为C++代码无效。 –

回答

4

让我们从格式化代码开始,跨越多行。这破坏了事实,这是一个奎因,但可以更容易地看到发生了什么:

char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}"; 

main() { 
    printf(s, 34, s, 34); 
} 

从本质上讲,这是一个字符串s这是一个printf - 格式化字符串的声明,其次是功能main的声明在四个参数上调用printf。 (main的这个定义在C中使用了老式的“暗含的int”规则,其中函数被假定为int作为返回类型,除非另有规定。我相信这在C中已被弃用,并且确定这不是合法的C++代码。)

那么究竟是什么printf调用?那么,它可能有助于注意,34是一个双引号,太行

printf(s, 34, s, 34); 

基本上是

printf(s, '"', s, '"'); 

这意味着“打印字符串s带参数"s ASCII码,和"。“那么s是什么?它在这里显示:

char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}"; 

在此之前,一个共同的自我参照的把戏。忽略%c%s%c部分,这基本上是程序其余部分的字符串表示。 %c%s%c部分发生在它变成自引用的地方。

那么如果你打电话printf(s, '"', s, '"')会发生什么?这将填充占位符%c%s%c"char*s=%c%s%c;main(){printf(s,34,s,34);}",这是字符串s的字符串内容。与串s的其余部分相结合,这因此proints

char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);"; 

这是该程序的源代码。我认为这很整洁 - 我知道的一个普通奎因程序的最接近的英文翻译是“打印此字符串,第二次用引号”(尝试它 - 看看会发生什么!),这基本上就是这样。

你在问为什么将数字更改为5和11并没有改变34被打印。这是正确的!字符串文字s有34个硬编码,因此将呼叫中的5和11更改为printf不会改变这一点。它将执行的操作不再是在字符串s的内部打印引号,而是打印非打印字符。

+0

感谢您对发生了什么的清晰解释。 – helloB