我刚刚遇到了这个问题,但没有人真正了解它是如何运作的: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 :(得分: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
内部的引号,而是打印非打印字符。