2015-08-28 212 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只是整个程序的一个副本。

相关问题