Ori Popowski
Ori Popowski

Reputation: 10662

How does casting a function actually work in C?

int foo(char *c)  {...}

main() {
     int (*thud)(void *);

     thud = (int (*)(void *))(foo);
}

What actually happens during the evaluation of the assignment?

There is a difference between the cast type and foo; the cast type is a pointer and foo is a function. So, does the compiler convert what's in '(foo)' into a pointer to foo and only then make the cast? Because nothing else seems to make sense; the other option is that the function itself is converted to a pointer to a function that gets a void* and returns an int, and as far as I know a function is a label to a piece of code in memory and thus cannot become a pointer, which is a variable.

Upvotes: 6

Views: 1629

Answers (5)

Jonathan Leffler
Jonathan Leffler

Reputation: 753805

This was going to be a comment to Rick C. Petty's answer - but it doesn't fit in 300 characters.

The C standard is not very restrictive - pointers to objects (and functions aren't objects) can be converted to 'pointer to void' and back without problem. POSIX requires that pointers to functions are all the same size and can be converted to pointer to void.

POSIX 2008 - General Information - The Compilation Environment

2.12.3 Pointer Types

All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

Note: The ISO C standard does not require this, but it is required for POSIX conformance.

Upvotes: 2

Rick C. Petty
Rick C. Petty

Reputation: 951

In C, absolutely nothing. It is just compiler glue to prevent you from doing something stupid. In C, the caller is responsible for maintaining the stack frame, so the cast is necessary when you invoke the function (i.e. arguments and the return value are pushed onto the stack). This makes it safe(r) since the caller's stack will not likely be mutated improperly. However, the invoked function can still mess up the caller's stack in certain rare cases.

I should clarify that the assignment copies the function pointer. But in C, all function pointers are just pointers. The type and casting is all compiler glue.

Another clarification: The standard specifies (in 6.5.2.2) that the behavior is undefined if the caller uses incompatible types. For example, casting a function which returns void into one which returns an int and then calling that function, the "returned" value is meaningless. It's a good idea to cast the function into a compatible type before calling it, or you may see unexpected results.

Upvotes: 5

ephemient
ephemient

Reputation: 204758

The name of a function is a pointer when used as such. It's somewhat similar to how the name of an array is a pointer to its first element.

That being said, calling a function through a pointer with a different type than the function's actual prototype (as your example does) is undefined behavior. Don't do it.

Addendum

If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

from section 6.3.2.3 of the C standard.

Upvotes: 5

avakar
avakar

Reputation: 32635

The correct term is decay. Function foo decays to a pointer to foo before the cast. The cast itself will be a no-op on all platforms I can think of.

Note, however, that the behavior of a program containing such a cast is undefined by the C standard.

Upvotes: 2

Varkhan
Varkhan

Reputation: 16761

A pointer in C is an address, i.e. a number stored in some place. A function in C is an address to some code. Those two are one of the same.

Upvotes: 2

Related Questions