obo*_*obo 148 c function-pointers
我发现C代码打印从1到1000没有循环或条件:但我不明白它是如何工作的.任何人都可以通过代码解释每一行吗?
#include <stdio.h>
#include <stdlib.h>
void main(int j) {
printf("%d\n", j);
(&main + (&exit - &main)*(j/1000))(j+1);
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*Mat 264
因为j<1000,j/1000为零(整数除法).所以:
(&main + (&exit - &main)*(j/1000))(j+1);
Run Code Online (Sandbox Code Playgroud)
相当于:
(&main + (&exit - &main)*0)(j+1);
Run Code Online (Sandbox Code Playgroud)
这是:
(&main)(j+1);
Run Code Online (Sandbox Code Playgroud)
哪个电话main用j+1.
如果j == 1000,则相同的行显示为:
(&main + (&exit - &main)*1)(j+1);
Run Code Online (Sandbox Code Playgroud)
归结为
(&exit)(j+1);
Run Code Online (Sandbox Code Playgroud)
哪个是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就可以了(但没有多大用处).
tda*_*ers 41
它使用递归,指针算法,并利用整数除法的舍入行为.
j/1000对于所有人来说j < 1000,这个词总计为0 ; 一旦j达到1000,则评估为1.
现在,如果你有a + (b - a) * n,n0或1,你最终得到aif n == 0和bif n == 1.使用&main(地址main())和&exit用于a和b的,术语(&main + (&exit - &main) * (j/1000))返回&main时j是低于1000,&exit否则.然后,生成的函数指针被赋予参数j+1.
整个结构导致递归行为:当j低于1000时,main递归调用自身; 当j达到1000时,它调用exit,使程序退出,退出代码为1001(这有点脏,但有效).