这个奎因是如何工作的?
How does this quine work?
我刚遇到这个 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!有人可以一步一步地指导我吗?
让我们首先格式化代码以跨越多行。这打破了它是奎因的事实,但更容易看到发生了什么:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
main() {
printf(s, 34, s, 34);
}
本质上,这是一个字符串 s
的声明,它是一个 printf
格式的字符串,后面跟着一个调用 printf
的函数 main
的声明四个参数。 (这个 main
的定义使用了 C 中老式的 "implicit int
" 规则,其中假定函数具有 int
作为 return 类型,除非另有说明。我相信这是目前在 C 中已弃用,并且可以肯定这不是合法的 C++ 代码。)
那么这个 printf
调用到底在做什么?好吧,注意到 34 是双引号的 ASCII 代码可能会有所帮助,所以行
printf(s, 34, s, 34);
本质上是
printf(s, '"', s, '"');
这意味着 "print the string s
with arguments "
, s
, and "
." 那么 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);";
这是程序的源代码。我认为这有点简洁 - 我所知道的一般 Quine 程序的最接近英文翻译是 "print this string, the second time in quotes"(尝试一下 - 看看会发生什么!),这基本上就是这样做的。
您问的是为什么将数字更改为 5 和 11 并没有改变正在打印的 34。没错!字符串文字 s
中硬编码了 34,因此在对 printf
的调用中更改 5 和 11 不会改变它。它所做的是不再打印字符串内部的引号 s
而是打印非打印字符。
我刚遇到这个 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!有人可以一步一步地指导我吗?
让我们首先格式化代码以跨越多行。这打破了它是奎因的事实,但更容易看到发生了什么:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
main() {
printf(s, 34, s, 34);
}
本质上,这是一个字符串 s
的声明,它是一个 printf
格式的字符串,后面跟着一个调用 printf
的函数 main
的声明四个参数。 (这个 main
的定义使用了 C 中老式的 "implicit int
" 规则,其中假定函数具有 int
作为 return 类型,除非另有说明。我相信这是目前在 C 中已弃用,并且可以肯定这不是合法的 C++ 代码。)
那么这个 printf
调用到底在做什么?好吧,注意到 34 是双引号的 ASCII 代码可能会有所帮助,所以行
printf(s, 34, s, 34);
本质上是
printf(s, '"', s, '"');
这意味着 "print the string s
with arguments "
, s
, and "
." 那么 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);";
这是程序的源代码。我认为这有点简洁 - 我所知道的一般 Quine 程序的最接近英文翻译是 "print this string, the second time in quotes"(尝试一下 - 看看会发生什么!),这基本上就是这样做的。
您问的是为什么将数字更改为 5 和 11 并没有改变正在打印的 34。没错!字符串文字 s
中硬编码了 34,因此在对 printf
的调用中更改 5 和 11 不会改变它。它所做的是不再打印字符串内部的引号 s
而是打印非打印字符。