tags:

views:

425

answers:

10

I'm trying to figure out what the following code in C does?

((void(*)())buf)();

where 'buf' is a char array.

+9  A: 

It casts buf to a function pointer of type void(*)() (A function returning nothing/void and taking unspecified arguments) and calls it.

The ANSI standard does not really allow the casting of normal data pointers to function pointers, but your platform may allow it.

iWerner
How come you can cast an array to a function pointer?? Is there some article that explains it?
Tony
A pointer is just a collection of bytes like any other value (which can thus be presented in C as an array of chars). You'll probably find that elsewhere in the program the reverse of this was done: `char *buf = (char *)function;` or something similar.
iWerner
You can do this because it's C -- you can do whatever you want. It's a terrible idea, but you can do it.
Clyde
What I'm saying is that it is not guaranteed to work. It is undefined behaviour in ANSI: On a Harvard architecture your program memory and data memory is physically separate, so a cast from a `char*` to a `void(*)()` does not make sense.
iWerner
Even on a von Neumann architecture, if segmentation is being used then a data pointer and a function pointer with the same value might point to different memory (the MS-DOS "Small" memory model is a real example of this).
caf
+1  A: 

I would guess that in many circumstances, it crashes the machine. Otherwise, it treats the array as a pointer to a function that returns void and invokes it.

plinth
+2  A: 

It casts buf into a function pointer, that takes unspecified arguments, and calls it.

Nick D
-1 (not really): takes unspecified arguments in C
pmg
@pmg, thanks. I edited by answer.
Nick D
+4  A: 

This casts buf to the type void (*)(), a pointer to a function that takes unspecified parameters and returns nothing. Then it calls the function at that address (the two rightmost parentheses).

Nick Meyer
-1 (not really): takes unspecified arguments in C
pmg
@pmg, good point.
Nick Meyer
A: 

calls a function pointer. the function has no arguments.

Function Pointer - Wikipedia

segy
-1 (not really): the function has unspecified arguments in C
pmg
The function has (is given) no arguments. The function type has unspecified parameters.
Steve Jessop
Granted, given the other answers I'll leave the post as it is.
segy
+20  A: 

Let's take it one step at a time.

void(*)()

This is a pointer to a function that takes unspecified arguments and has no return value.

(void(*)())buf

simply casts buf to this function pointer type. Finally,

((void(*)())buf)();

calls this function.

So the entire statement is "interpret buf as a pointer to a void function without arguments, and call that function."

Thomas
Casting a character buffer into a function and calling it is evil. It's either an attempt at self modifying code, or it's a malicious intent to do some sort of exploit. Either way, avoid it at all costs.
Paul Tomblin
Correct me if I'm wrong, but isn't it the value of the pointer (the address of the array) that is treated as a function, not the contents of the array? "interpret *the value* in buf" sounds a little bit like you're saying the contents are interpreted as a pointer to a function.
Nick Meyer
-1 (not really): takes unspecified arguments in C
pmg
@Paul: more probably code generation, but still your complaints apply, of course. :)
unwind
I know it is malicious code, but I was just trying to understand it. I would never use it!
Tony
@Nick Meyer: You're right, fixed it.@pmg: Fixed that, too. I'll take your word for it, but do you have a reference?Thank you both.
Thomas
Note that C makes no guarantee that a data pointer has the same size as a function pointer.
vonolsson
@Thomas: 6.5.2.2/6 in n1401.pdf (the latest draft of the Standard). A function declaration without arguments does not provide a prototype; and `void(*)()` is such a declaration.
pmg
@vonolsson: Quite aside from pointer size, C makes no guarantee that memory allocated on either the stack or the heap is executable. This code should only appear in a JIT or equivalent, and necessarily is platform-specific. Assuming that buf has just been filled with machine instructions, the line before the quoted cast-and-call should probably be some kind of platform-specific operation to flush the icache.
Steve Jessop
@Paul Tomblin: seriously, avoid JITs at all cost? Or do you just mean, don't write them in C?
Steve Jessop
+2  A: 
((void(*)())buf)();
 \------------/         cast `buf` to
 \---------/            type: pointer to function accepting a fixed but
                              unspecified number of arguments and
                              returning void
\----------------/      and call that "function"
pmg
+1 You are correct about the unspecified number of parameters. If you had clarified with an example, you'd probably have gotten more appreciation for your insight :)
Andomar
+1  A: 

You might find "expert c programming" a good read - unpacking this kind of thing is in one of the chapters, if I remember right. It's a long time since I read it, but I remember thinking it was worth the effort at the time. http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298

andrew cooke
+5  A: 

I tend to use the "cdecl" command when I come across a mind boggling declaration. Example:

[me@machine]$ cdecl
Type `help' or `?' for help
cdecl> explain (void(*)())buf
cast buf into pointer to function returning void

Although there are cases where I do wish that there's a tool out there that explains the output of "cdecl" :/

lsc
+1  A: 

There is an online version of the 'cdecl' tool that lsc mentioned that you might find useful : http://www.cdecl.org/

madman1969