21

((void(*)(void))0)();

So we have integer 0 type casting to this tricky type (void(*))(void) and then executing it. Source claims that this should work, but what does it actually?

This must be one of those C jokes like #define TRUE FALSE, I suppose.

user2984878
  • 213
  • 1
  • 2
  • 5

5 Answers5

33

This is a function expecting no arguments and returning no value:

void f(void)

This is a pointer to a function expecting no arguments and returning no value:

void (*p)(void)

This is the type of that pointer:

void (*)(void) /* just remove the p! */

This is that type in parentheses:

(void (*)(void))

This is a cast to that type (the type in parentheses, followed by a value):

(void (*)(void))0

Still with me? so far we have the integer value 0 cast to a pointer-to-function-that-takes-no-arguments-and-returns-nothing.

The cast is an expression with pointer-to-function type. When you have one of those you can call it like this:

(your expression here)(arguments to the function)

The first set of parentheses are just for precedence, and sometimes might not be needed (but this time they are). The end result:

((void (*)(void))0)(/* no args */);

Takes the value 0, casts it to pointer-to-function-expecting-no-arguments-and-returning-nothing, and calls it, supply no arguments.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 2
    You could also add: 0 is the address where the function(taking no arguments and returning void) resides. – AlphaGoku May 02 '16 at 06:50
  • Take this for some more infos about function pointers: https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work#840504 – Cutton Eye Oct 22 '18 at 08:30
17

The syntax to cast address to a function pointer and then call it would look like this:

((void (*)(void))address)();

It might be clearer to do something like this though:

void (*fptr)(void) = (void (*)(void))address;
fptr();

Said that ((void(*)(void))0)(); instruction is used to jump to 0 in firmwares usually. It is a bit improper because it actually calls in 0 instead of jumping to 0, but practically it won't make any difference (a fw hot reboot will be performed)

alk
  • 69,737
  • 10
  • 105
  • 255
Jekyll
  • 1,434
  • 11
  • 13
  • What does "*fw*" mean, please? – alk Dec 03 '13 at 17:10
  • 3
    firmware, there is the boot address is usually in 0 (or 0xFFFF0000 for arm or i386), this jump (call) will cause the processor hot restart. If you want more information look for ***jump to reset vector*** – Jekyll Dec 03 '13 at 17:12
  • @ShafikYaghmour I will look for it, in the meantime you can see a small variant in Arduino at http://learn.adafruit.com/system/assets/assets/000/010/293/original/ATmegaBOOT_168.c Note that this reset is not very suitable for big controllers (like ARM11 or more recent) in which usually it is fired an internal watchdog in order to achieve a more "secure" HW reset. – Jekyll Dec 03 '13 at 17:44
10

This treats NULL as a function pointer and executes it, it should raise a sigbus or similar on most systems.

void(*)(void)   <- type, function pointer taking no arguments and returning no value
(void(*)(void)) <- cast to above type
((...)0)        <- cast NULL/0 to said type
((...)0)()      <- execute the cast value as a function
Kevin
  • 53,822
  • 15
  • 101
  • 132
3

On some embedded system (AVR microcontroller, for example) this might be a way to implement a jump (a call, really) to the reset vector.

You could restart the SW this way, especially if you have disabled interrupts before this.

teroi
  • 1,087
  • 10
  • 19
3

The AVR's will normally load the user application program at address 0. A bootloader program which is loaded at a much higher address, might jump to (call the function at) address 0. So, the cast and call to the 0 address is a useful construct in this environment.