jxh*_*jxh 3 c quine language-lawyer
以下程序看起来像一个调用自身的C宏.
#define q(k)int puts();int main(){puts(#k"\nq("#k")");}
q(#define q(k)int puts();int main(){puts(#k"\nq("#k")");})
Run Code Online (Sandbox Code Playgroud)
它编译并运行良好.它打印出来.
这段代码真的是C吗?也就是说,它是否依赖于标准C之外的任何东西才能正常工作?
@devnull指出这个问题有一个类似的程序:
#define q(k)main(){return!puts(#k"\nq("#k")");}
q(#define q(k)main(){return!puts(#k"\nq("#k")");})
Run Code Online (Sandbox Code Playgroud)
该程序是否依赖标准C之外的任何东西才能正常工作?
第一个程序是在C中实现quine的一个例子.在高级别,它定义了一个宏q(),它创建了一个main()打印出两行的定义.第一行是参数本身,第二行是包含在对q()自身的调用中的参数.那么,以下程序:
#define q(k)int puts();int main(){puts(#k"\nq("#k")");}
q(foo)
Run Code Online (Sandbox Code Playgroud)
扩展到:
int puts();int main(){puts("foo""\nq(""foo"")");}
Run Code Online (Sandbox Code Playgroud)
编译并运行时,会产生输出:
foo
q(foo)
Run Code Online (Sandbox Code Playgroud)
用宏定义本身代替fooquine中的结果.宏并不真正调用自身,它是在定义它的同一文本上调用的.在C中,宏不是递归扩展的(C.99§6.10.3.42).
如问题中所述,该程序使用严格的C.99设置(-pedantic -std=c99)在GCC下进行编译而无需投诉.该程序仅使用标准C功能,并符合C.99和C.11.
#"字符串化"运算符(C.99§6.10.3.2).main()返回值(C.99§5.1.2.2.31).特别值得注意的是,该程序不依赖于字符的ASCII编码.
该程序将在C.89-90编译器上编译,但main()不为C.89-90定义不返回值的行为.通过return 0;在调用之后添加,可以对程序进行简单修改以符合C.89-90标准puts().
至于第二个项目,它也是一个quine.但是,它不是C.89-90,也不是C.99,也不符合C.11.这是因为它依赖于puts()返回逻辑非运算符的正数,以便返回值0.但是,C只需要puts()在成功时返回非负值(C.99§7.19.7.103).只有C.89-90允许隐式函数声明(C.89,§3.3.2.2).通过删除return!,然后return 0;在puts()通话后添加,可以修改程序以符合C.89-90 .
这些课程的结构在很大程度上受到了"虚构"语言BlooP的quine项目的启发,该项目由道格拉斯·R·霍夫施塔特(Douglas R. Hofstadter)撰写的哥德尔,埃舍尔,巴赫:永恒的金色辫子一书中提出(由于创造了这个术语而得到了认可)奎因).
DEFINE PROCEDURE "ENIUQ" [TEMPLATE]: PRINT [TEMPLATE, LEFT-BRACKET,
QUOTE-MARK, TEMPLATE, QUOTE-MARK, RIGHT-BRACKET, PERIOD].
ENIUQ
['DEFINE PROCEDURE "ENIUQ" [TEMPLATE]: PRINT [TEMPLATE, LEFT-BRACKET,
QUOTE-MARK, TEMPLATE, QUOTE-MARK, RIGHT-BRACKET, PERIOD].
ENIUQ'].
Run Code Online (Sandbox Code Playgroud)
顺便说一下,这是一个程序的版本,它以相反的顺序打印出它的源代码:
#define q(k)r(char*s){if(*s)r(s+1);putchar(*s);}main(){r(#k"\nq("#k")\n");}
q(#define q(k)r(char*s){if(*s)r(s+1);putchar(*s);}main(){r(#k"\nq("#k")\n");})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
542 次 |
| 最近记录: |