这个quine怎么样?

时间:2015-11-05 00:31:35

标签: c quine

我刚刚遇到了这个问题,但没有人真正了解它是如何运作的: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!有人可以一步一步地指导我吗?

1 个答案:

答案 0 :(得分:6)

让我们首先将代码格式化为多行。这打破了它是一个quine的事实,但更容易看到发生了什么:

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是双引号的ASCII代码,所以行

printf(s, 34, s, 34);

基本上是

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

这意味着“使用参数s"s打印字符串"。”那是什么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的其余部分,因此提示

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

这是该程序的源代码。我觉得这有点整齐 - 我知道的一般Quine程序的最接近的英文翻译是“打印这个字符串,第二次用引号”(尝试一下 - 看看会发生什么!),这基本上就是这样。

你问为什么将数字改为5和11并没有改变34正在打印。那是对的!字符串文字s有34个硬编码,因此在调用printf时更改5和11不会改变它。它将不再打印字符串s内部的引号,而是打印非打印字符。