Home > Guides > Programming > C/C++

Pointers to Functions

Last updated Jul 4, 2003.

Pointers to Functions

While many programming languges support the concept of pointers to data, only a few enable you to define pointers to code -- that is, pointers that point to functions.

Originally introduced in C, pointers to functions are widely used in C++, although pointers to member functions provide similar functionality in the case of class objects. Pointers to functions ("function pointers" for short) are useful in implementing callbacks, dynamic binding, and event-based applications.

Unfortunately, their cumbersome syntax baffles both novices and experienced programmers. In this section, I will focus on traditional C function pointers and explain how to declare and use them effectively. This will serve as the basis for pointers to members, which I will discuss in a different section.

Declaring a Function Pointer

A callback function is one that is not invoked explicitly by the programmer. Rather, the responsibility for its invocation is delegated to another function that receives its address.

To implement a callback, you first need to define an appropriate function pointer. The syntax may seem a bit arcane, but if you're familiar with function declarations in general, you may realize that a function pointer declaration is similar to a function declaration. Consider the following function prototype:

void f();

It declares a function called f() that takes no arguments and returns void. A pointer to such a function has the following type:

void (*) (); //type of f()

Let's parse it. The asterisk in the leftmost pair of parentheses is the nucleus of a function pointer declaration. Two additional elements in a function pointer declaration are the return type (void in this example), and a parameter list enclosed in the rightmost pair of parentheses (empty in this example). Note that this declaration didn't create a pointer variable yet -- it only declared the type of such a variable. So, what is it good for? You can use this type in a typedef declaration, in a sizeof expression, or as a function parameter:

// get the size of a function pointer
unsigned psize = sizeof (void (*) ()); 
// declare a typedef for a function pointer
typedef void (*pfv) ();
// used as a function parameter
void signal( void (*)() );

pfv is a synonym for "a pointer to a function that takes no arguments and returns void." You can use this typedef name to hide the cumbersome syntax of function pointers.

A pointer variable, of course, has a name. Here is an example:

void (*p) (); // p is a pointer to a function 

The name of a pointer variable appears right before the nucleus, enclosed in parentheses. You can now bind a function to p by assigning it the name of a function that has a matching signature (parameter list) and return type. For example:

void func() 
{
 /* do something */
} 
p=func; 

You may bind a different value to p so long as it's an address of a function with the same signature and return type. However, a function's name is not a part of its type.

Passing a Callback Function's Address to Its Caller

Once you've assigned a value to p you can execute the callee (the bound function) through it. To call a function through a pointer, simply treat it as if it were the function itself:

p(); //call the function bound to p

You can also pass p to another function which will invoke the callee without knowing its name:

void caller(void(*p)())
{
 p(); // call the bound function
}
void func();
int main()
{
 p = func; 
 caller(p); // pass address of func to caller
}

Remember that the assignment to p may take place at runtime, which enables you to implement dynamic binding.

Calling Conventions

So far, I've discussed function pointers without discussing compiler-specific conventions that aren't defined by the ISO standard. Many compilers have several calling conventions. For example, in Visual C++ you can precede __cdecl, __stdcall or __pascal to a function's prototype to indicate its calling convention. Borland's C++ Builder also supports the __fastcall calling convention.

A calling convention affects the compiler-generated name of a given function (i.e., its mangled name), the direction of arguments (right to left or left to right), stack cleanup responsibility (by the caller or the callee), and the mechanism for argument passing (stack, CPU registers, etc.). A calling convention is an integral part of a function's type; therefore, you can't assign an address of a function to a pointer with an incompatible calling convention. For example:

// callee is a function that takes int and returns int
__stdcall int signal(int); 

// caller is a function that takes a function pointer
void caller( __cdecl int(*ptr)(int)); 

// illegal attempt to store the address of callee in p
__cdecl int(*p)(int) = signal; // error

p and signal() have incompatible types because they have different calling conventions, although both have the same signature and return type.

Function Pointers and Ordinary Pointers

While function pointers share many similarities with ordinary data pointers, they differ in several ways. First, you can't declare a generic pointer to function similar to void*. In addition, trying to store a function pointer in a void* isn't guaranteed to work (certain compilers tolerate this, others don't). Finally, you can't dereference a function pointer -- there's no such thing as passing a function by value.

Summary

Function pointers are a powerful feature. You'll find them in the heart of almost every large-scale application. Familiarity with this feature is therefore essential for professional programmers.

To disguise the cumbersome syntax, you can use typedef names. As a C++ programmer you're probably wondering why you should bother about this C feature when C++ has better alternatives in the form of pointers to member functions and function objects. There are at least two compelling reasons for using them in C++: code that uses C functions (say, the <ctime> and <csignal> libraries which have no object-oriented alternative in C++) and static member functions. Unlike pointers to nonstatic member functions, pointers to static member functions are C function pointers, not pointers to member functions.

Discussions

What is Required of a Move Constructor
Posted Jul 18, 2010 09:52 AM by alex14637
2 Replies
Bugzilla
Posted Nov 18, 2008 01:53 AM by cupu
2 Replies
i want c++ book through net
Posted Aug 23, 2007 11:13 PM by harivilu
3 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Danny KalevYves Smith: Suspicions that The Fed is manipulating Wall Street
By Danny KalevMay 24, 2010 No Comments

Yves Smith, the nom de plume of the creator of Naked Capitalism and one of the most savvy and respected members of the blogosphere. In professional life Yves is known as Susan Webber. Yves recently gave an interview to an Israeli financial newspaper in which she claims that a federal team unofficially called "the plunge protection team" is manipulating the stocks on Wall Street.

Danny KaleviPhone OS 4.0 SDK License Controversy
By Danny KalevApril 17, 2010 1 Comment

The much-discussed software development kit for the upcoming iPhone OS 4.0 says that native applications must be "originally written" in Objective C, C, or C++", forbidding developers from using any sort of "translation or compatibility layer." This legalese seems to rule out just about anything you can think of -- translating an application written in any other language to C++. However, this stern interpretation is probably exaggerated. Besides, when you consider the outcry and criticism with which Apple's license was greeted, you can't help but wondering where all these freedom of expression activists were when Sun -- and later Microsoft and Google -- imposed similar draconian restrictions on developers.

Danny KalevBjarne Stroustrups's Stevens Talk
By Danny KalevDecember 7, 2009 No Comments

On 2nd December Bjarne Stroustrup delivered a talk about the standardization process of C++0x at the Stevens institute. Here some of the key points from his talk.

See More Blogs

Informit Network