Как работает программа выводящий собственный код на С?
Есть програмка, которая выводит свой же код:
#include <stdio.h>
int main() {
const char *code =
"#include <stdio.h>\n\n"
"int main() {\n"
" const char *code = \n"
" \"%s\";\n"
" printf(code, code);\n"
" return 0;\n"
"}\n";
printf(code, code);
return 0;
}
Можете подробно объяснить как она работает, почему в printf() дважды передается code?
Вот как я пока что понимаю: мы первым аргументом передаем строку т.е code и внутри этой строки есть спецификатор %s и далее через запятую мы передаем ещё раз code чтобы вставить вместо этого спецификатора.
Ответы (1 шт):
Плохо работает программа. Она выводит что-то отдалённо похожее на свой код, но этого недостаточно.
| оригинал | печать |
|---|---|
#include <stdio.h> |
#include <stdio.h> |
Да, вы разобрались верно: через трюк с печатью форматной строки через саму себя, программа пытается напечатать свой код два раза. Это первый шаг к созданию полноценного квайна.
Попробуйте разобраться как устроена программа ниже. Она печатает каждую свою строку два раза: один раз как код, второй – как строковый литерал из массива code:
#include <stdio.h>
const char *code[] = {
"#include <stdio.h>",
"",
"const char *code[] = {",
"};",
"",
"int main() {",
" for (int i = 0; i < 3; ++i) {",
" puts(code[i]);",
" }",
" for (int i = 0; i < 24; ++i) {",
" fputs(\" \\\"\", stdout);",
" for (const char *s = code[i]; *s != '\\0'; ++s) {",
" switch (*s) {",
" case '\"' : fputs(\"\\\\\\\"\", stdout); break;",
" case '\\\\': fputs(\"\\\\\\\\\", stdout); break;",
" default : putchar(*s) ; break;",
" }",
" }",
" puts(\"\\\",\");",
" }",
" for (int i = 3; i < 24; ++i) {",
" puts(code[i]);",
" }",
"}",
};
int main() {
for (int i = 0; i < 3; ++i) {
puts(code[i]);
}
for (int i = 0; i < 24; ++i) {
fputs(" \"", stdout);
for (const char *s = code[i]; *s != '\0'; ++s) {
switch (*s) {
case '"' : fputs("\\\"", stdout); break;
case '\\': fputs("\\\\", stdout); break;
default : putchar(*s) ; break;
}
}
puts("\",");
}
for (int i = 3; i < 24; ++i) {
puts(code[i]);
}
}