1

I just came across this quine question, but no one really went into how it works: 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);}

What I especially don't understand is the following has the same output even though I changed the ints:

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

It still prints the 34s! Can someone walk me through this step by step?

4

1 回答 1

11

让我们首先将代码格式化为跨越多行。这打破了它是 quine 的事实,但更容易看到正在发生的事情:

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

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

本质上,这是一个字符串的声明,s它是一个printf格式化字符串,然后是一个main调用printf四个参数的函数的声明。(这个定义在 C 中main使用老式的“隐式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 个硬编码,因此更改调用中的 5 和 11printf不会改变它。它将不再在字符串内部打印引号s,而是打印非打印字符。

于 2015-11-05T01:36:20.483 回答