2015-11-05 1 views
0

Я просто наткнулся на этот Куайн вопрос, но никто не вошел в, как это работает: 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

Что он печатает после 'char * s =' и перед вторым '; main() {'?(где кавычки должны быть) – immibis

+3

Что это связано с заголовком? – user2357112

+0

'char * s =" blah ";' недопустим как код на C++. –

ответ

4

Начнем с форматирования кода для размещения нескольких строк. Это нарушает тот факт, что это Куайн, но и делает его легче увидеть, что происходит:

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

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

По сути, это декларация строки s это printf строку в формате, с последующим заявлением функции main который вызывает printf по четырем аргументам. (Это определение main использует старомодное «неявное правило int» в C, где предполагается, что функции имеют 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, это поэтому proints

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 и 11 в вызове printf не изменит это. То, что он будет делать, больше не печатает кавычки во внутренней части строки s и вместо этого печатает непечатаемые символы.

+0

Спасибо за такое четкое объяснение происходящего. – helloB