我发现打印出的C代码从1到1000都没有循环或有条件:但是我不明白它是如何工作的。任何人都可以遍历代码并解释每一行吗?
#include <stdio.h>
#include <stdlib.h>
void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}
          我发现打印出的C代码从1到1000都没有循环或有条件:但是我不明白它是如何工作的。任何人都可以遍历代码并解释每一行吗?
#include <stdio.h>
#include <stdlib.h>
void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}
          Answers:
对于j<1000,j/1000为零(整数除法)。所以:
(&main + (&exit - &main)*(j/1000))(j+1);
等效于:
(&main + (&exit - &main)*0)(j+1);
这是:
(&main)(j+1);
这就要求main用j+1。
如果为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:
函数指示符是具有函数类型的表达式。除非是sizeof运算符或一元&运算符的操作数,否则类型为“ 函数返回类型 ” 的函数指示符将转换为具有类型为“ 函数返回类型的指针 ”的表达式。
exit是一个功能指示符。即使没有一元&地址运算符,它也被视为函数的指针。(这&使得它很明确。)
§6.5.2.2/ 1及以下内容描述了函数调用:
表示被调用函数的表达式应具有指向函数的类型指针,该函数返回void或返回数组类型以外的对象类型。
exit(j+1)之所以如此,是因为将函数类型自动转换为指向函数的指针类型,并且(&exit)(j+1)也可以将其显式转换为指向函数的指针类型。
话虽如此,上面的代码不符合要求(main要么接受两个参数,要么不接受任何参数),并且&exit - &main我认为根据§6.5.6/ 9仍未定义:
当减去两个指针时,两个指针都应指向同一数组对象的元素,或者指向数组对象的最后一个元素;...
加入(&main + ...)将是自身有效的,并且可以使用,如果添加量是零,因为§6.5.6/ 7说:
就这些运算符而言,指向不是数组元素的对象的指针的行为与指向长度为1且对象类型为其元素类型的数组的第一个元素的指针的行为相同。
因此,将零添加到&main是可以的(但使用不多)。
foo是一个指针,&foo是该指针的地址。在第二种情况下,foo是一个数组,&foo等效于foo。
                    ((void(*[])()){main, exit})[j / 1000](j + 1);
                    &foo与foo数组不同。&foo是指向数组foo的指针,是指向第一个元素的指针。它们确实具有相同的价值。对于函数,fun和&fun都是函数的指针。
                    它使用递归,指针算法,并利用整数除法的舍入行为。
该项j/1000对所有取整至0 j < 1000; 一旦j达到1000,则评估为1。
现在,如果您拥有a + (b - a) * n,其中where n为0或1,则最终得到aif n == 0和bif n == 1。使用&main(的地址main())和&exitfor a和b,该术语在低于1000 时(&main + (&exit - &main) * (j/1000))返回,否则返回。然后将结果函数指针送入参数。&mainj&exitj+1
整个构造导致递归行为:j小于1000时,main递归调用自身;否则,递归调用。当j达到1000时,它将exit改为调用,使程序以退出代码1001退出(这有点脏,但是可以使用)。
exit,该函数将退出代码作为其参数,然后退出当前进程。此时,j为1000,因此j + 1等于1001,这成为退出代码。
                    
main使用C ++进行调用。