For j<1000
, j/1000
is zero (integer division). So:
(&main + (&exit - &main)*(j/1000))(j+1);
is equivalent to:
(&main + (&exit - &main)*0)(j+1);
Which is:
(&main)(j+1);
Which calls main
with j+1
.
If j == 1000
, then the same lines comes out as:
(&main + (&exit - &main)*1)(j+1);
Which boils down to
(&exit)(j+1);
Which is exit(j+1)
and leaves the program.
(&exit)(j+1)
and exit(j+1)
are essentially the same thing - quoting C99 §6.3.2.1/4:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
exit
is a function designator. Even without the unary &
address-of operator, it is treated as a pointer to function. (The &
just makes it explicit.)
And function calls are described in §6.5.2.2/1 and following:
The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.
So exit(j+1)
works because of the automatic conversion of the function type to a pointer-to-function type, and (&exit)(j+1)
works as well with an explicit conversion to a pointer-to-function type.
That being said, the above code is not conforming (main
takes either two arguments or none at all), and &exit - &main
is, I believe, undefined according to §6.5.6/9:
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; ...
The addition (&main + ...)
would be valid in itself, and could be used, if the quantity added was zero, since §6.5.6/7 says:
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
So adding zero to &main
would be ok (but not much use).
It uses recursion, pointer arithmetic, and exploits the rounding behavior of integer division.
The j/1000
term rounds down to 0 for all j < 1000
; once j
reaches 1000, it evaluates to 1.
Now if you have a + (b - a) * n
, where n
is either 0 or 1, you end up with a
if n == 0
, and b
if n == 1
. Using &main
(the address of main()
) and &exit
for a
and b
, the term (&main + (&exit - &main) * (j/1000))
returns &main
when j
is below 1000, &exit
otherwise. The resulting function pointer is then fed the argument j+1
.
This whole construct results in recursive behavior: while j
is below 1000, main
calls itself recursively; when j
reaches 1000, it calls exit
instead, making the program exit with exit code 1001 (which is kind of dirty, but works).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With