2015-08-28 72 views
8

我越想明白這個困惑的謎團就越想放棄。程序哪個源代碼與其輸出完全相同

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

如何發生的這一行的源代碼,當程序運行並且是有這種程序的任何共同的概念,產生完全相同的輸出?

+2

你知道'printf'的作用嗎?你可以計算出什麼'printf(「char * s =%c%s%c; main(){printf(s,34,s,34);}」,34,「char * s =%c%s% c; main(){printf(s,34,s,34);}「,34)'打印,因爲34是ASCII代碼的一個'''? – immibis

+0

現在它是官方的 - 我非常缺乏分析技能 – Malina

+0

我知道什麼是34和printf是什麼..它只是在語義上讓我困惑 – Malina

回答

11

這被稱爲Quine

那麼讓我們來看看main()做:

printf(s,34,s,34); 

34是字符"(雙引號)的ASCII碼,所以這是一樣的:

printf(s, '"', s, '"'); 

的第一個參數printf(3)是格式字符串。傳遞的字符串是:

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

所以,printf(3)將輸出正是這樣,但要注意%c%s%c格式說明,它指示printf(3)打印字符,然後是字符串,然後在另一個字符地點,分別是第二,第三和第四個參數。

正如我們所看到的,字符都是",字符串是s(相同的字符串)。因此,該程序的輸出是:

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

X是在程序中的字符串s。所以我們得到這個作爲輸出:

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

其中,有趣的是,程序源本身。

+0

不可避免地解釋 - 混淆;所以我認爲不給這個給學生是一個奇妙的想法。謝謝:) – Malina

+1

@Malina事實上,它未經訓練的學生眼睛可能會很棘手,但自我複製程序是可計算性理論的重要組成部分。學生至少應該學習這個概念。 –

+0

我也更新了這個問題,以使其他人在閱讀你的答案的同時增加更多的價值。 – Malina

3

採取從printf的第一參數即字符串:

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

和做替代其中

%c = 34 = '"' //(same for both %c) 
%s = 'char *s = %c%s%c; main(){printf(s,34,s,34);}' 

的printf將做替代只有一次(未遞歸),所以結果是:

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

理解代碼,第一簡化並重新格式化:

char *s = "some format string"; 
main() { 
    printf(s,34,s,34); 
} 

所以它使用s作爲格式化字符串打印三個實體:34,字符串s本身34。在這種情況下,格式化字符串s的重要組成部分是:

char *s = "... %c%s%c ..." 

這意味着兩個34小號成爲雙引號(")和格式串s只是打印爲正常的字符串。現在你應該看到其餘的的格式化字符串s只是整個程序的一個副本。

相關問題