Самовоспроизводящаяся программа - PullRequest
10 голосов
/ 22 декабря 2011
main(a){printf(a="main(a){printf(a=%c%s%c,34,a,34);}",34,a,34);}

Как он воспроизводит себя после компиляции? Какова роль написания 34 в функции printf?

1 Ответ

18 голосов
/ 22 декабря 2011

34 - код символа ASCII для символа двойной кавычки (").


Чтобы прокомментировать мой тангенциальный комментарий (это была ссылка на «Годеля Эшера Баха» Хофштадтера), это работает, потому что это квин, который в основном представляет собой рецепт, содержащий два элемента: ядро ​​данных и операцию над этим ядром. , так что, когда операция завершена, воспроизводится оригинальный рецепт. Для этого ядро ​​и операция практически идентичны. В упомянутой программе ядром является строка

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

и операция выполняется остальной частью программы:

 main(a){printf(a=_____,34,a,34);}

где ____ - ядро. Вы заметите, что они выглядят по существу одинаково: операция может печатать сама себя, используя ядро ​​в качестве спецификатора формата (который печатает ядро, но без кавычек, превращая ядро ​​в операцию в выводе), а также подает само ядро ​​как параметр в спецификаторе формата (%s) и его кавычки, в результате чего выводится ядро.

операция (ядро в кавычках) => ядро ​​без кавычек, содержащее копию ядра, а в кавычках => исходная программа.


еще один момент: причина, по которой он использует эти 34 операции, заключается в том, что он упрощает операцию цитирования, используя ядро ​​без символов кавычек; если вы пытались использовать

"main(a){printf(a=\"%s\",a);}"

в качестве ядра, с ядром без кавычек

main(a){printf(a="%s",a);}

это было бы намного сложнее, потому что для того, чтобы заключить в кавычки ядро, вам нужно было поставить обратную косую черту в кавычках в середине строки.

...