从1到1000打印没有循环或条件语句的C代码是如何工作的?

我发现C代码打印从1到1000没有循环或条件 :但我不明白它是如何工作的。 任何人都可以通过代码并解释每一行?

 #include <stdio.h> #include <stdlib.h> void main(int j) { printf("%d\n", j); (&main + (&exit - &main)*(j/1000))(j+1); } 

不要这样写代码。


对于j<1000j/1000是零(整数除法)。 所以:

 (&main + (&exit - &main)*(j/1000))(j+1); 

相当于:

 (&main + (&exit - &main)*0)(j+1); 

这是:

 (&main)(j+1); 

哪个调用j+1 main

如果j == 1000 ,那么相同的线出来:

 (&main + (&exit - &main)*1)(j+1); 

归结到

 (&exit)(j+1); 

这是exit(j+1)并离开程序。


(&exit)(j+1)exit(j+1)基本上是相同的东西 – 引用C99§6.3.2.1/ 4:

函数指示符是具有函数types的expression式。 除了sizeof运算符或一元运算符的操作数外,types为“ 函数返回types ”的函数标识符被转换为types为“ 指向函数返回types的指针 ”的expression式。

exit是一个函数标识符。 即使没有一元操作符&地址操作符,它也被视为一个指向函数的指针。 ( &只是使其明确。)

函数调用在§6.5.2.2/ 1和下面描述:

表示被调用函数的expression式应该有指向返回void的函数的types指针,或者返回除数组types以外的对象types。

因此, exit(j+1)是因为函数types自动转换为指针函数types,并且(&exit)(j+1)工作得很好,并且显式转换为指针函数types。

这就是说,上面的代码是不符合( main采取两个参数或根本没有), &exit - &main是,我相信,根据§6.5.6/ 9未定义:

当减去两个指针时, 都应指向同一个数组对象的元素 ,或指向数组对象的最后一个元素的元素; …

添加(&main + ...)本身是有效的, 如果添加的数量为零,可以使用,因为§6.5.6/ 7说:

对于这些运算符而言,指向不是数组元素的对象的指针的行为与以对象types作为其元素types的长度为1的数组的第一个元素的指针相同。

因此,将零加到&main将是可以的(但没有多大用处)。

它使用recursion,指针算术,并利用整数除法的舍入行为。

所有j < 1000j/1000项下降到0; 一旦j达到1000,它评估为1。

现在,如果你有a + (b - a) * n ,其中n是0或者1,那么最终得到a if n == 0 ,而b如果n == 1 。 对于ab ,使用&mainmain() )的地址和&exit ,当j低于1000时, (&main + (&exit - &main) * (j/1000))返回&main ,否则&exit 。 所得到的函数指针然后被馈送参数j+1

这个整个结构导致recursion行为:当j低于1000时, mainrecursion地调用它自己; 当j达到1000时,它会调用exit来使程序退出,退出代码为1001(这很脏但是可行)。