10

I think I may be suffering from the dreaded "accidental programmer" disease, at least when it comes to typedefs and function pointers. So I've been experimenting with all kinds of combinations involving these to analyse the results based on all the output I get.

But as I kept on trying different combinations, instead of analyzing the results I'm now just lost in process.

I'm hoping you guys will help me figure out this mess.

First code example

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = &do_something;
pr(); // Hello World

Second code example

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = do_something;
pr(); // Hello World

How do both the above code examples work, it's as if '&' has no effect on function name

third code example

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print pr;
pr = do_something; // compile error
pr = &do_something; // compile error
pr();

I was hoping one of the above assignments to work here but damn! I really don't understand function pointers (and maybe typedef too).

3
  • 1
    This may help stackoverflow.com/questions/4298654/… Commented Feb 20, 2012 at 7:25
  • Umm... I think you should get yourself a 'Expert C Programming' it explians C's var define rules. I'll try to find it online for you Commented Feb 20, 2012 at 7:27
  • 1
    just google Expert C programming, the first one is the book. Search 'How a Declaration Is Formed' and I think you'll get the answer Commented Feb 20, 2012 at 7:33

4 Answers 4

19

The address of a function name and the plain function name both mean the same thing, so & has no effect on a function name.

Similarly, when using function pointers, multiple dereferencing isn't a problem:

#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }

int main(void)
{
    print *f1 = dosomething;
    print *f2 = &dosomething;
    f2();
    (f1)();
    (*f1)();
    (**f2)();
    (***f1)();
    (****f2)();
    (*****f1)();
}

That compiles cleanly under:

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -std=c99 xx.c -o xx

I would not claim that multiple stars is good style; it isn't. It is 'odd, and (yes, you may say it) perverse'. One is sufficient (and the one star is mainly for people like me who learned to program in C before the standard said "it is OK to call a function via a pointer without using the (*pointer_to_function)(arg1, arg2) notation; you can just write pointer_to_function(arg1, arg2) if you like"). Yes, it is weird. No, no other type (or class of types) exhibits the same behaviour, thank goodness.

Sign up to request clarification or add additional context in comments.

3 Comments

Now that is odd and, may I say, perverse. To try and to actually compile. :)
+1, to make it clear, functions and function pointers aren't the same, but the former tends to automatically decay to the latter in most contexts (though not all). In the expression **f2, the function pointer gets dereferenced and the resulting function immediately decays back to a pointer, which is then again dereferenced.
Arrays have a similar, though not identical, "automatic decay" behavior. For int x[10];, the addresses of x and &x are the same. But their type is different, and you can't use the nice starry tower shown here.
8

The thing about function pointers is that they're function pointers! :-) This is how you get your third sample to work:

#include <stdio.h>
typedef void (*print)(void);
//            ^
void do_something (void) { printf("Hello World\n"); }
int main (void) {
    print pr;
    pr = do_something; // &do_something would also work.
    pr();
    return 0;
}

In terms of whether you use funcName or &funcName, it doesn't matter (in C at least). Section 6.3.2.1 Lvalues, arrays and function designators states:

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".

Comments

3

It turns out that, in C/C++, both funcname and &funcname will yield the address of funcname and can be assigned to a function pointer variable. This is actually just an oddity of how the syntax was designed for the language(s).

Comments

3

Like C, C++ has pointer to functions: void (*)() for example is a pointer to a function that takes no argument and returns no value. However, C++ has also introduced references to functions void (&)() and there are implicit conversions between the two (though I don't remember the rules exactly).

Therefore:

  • funcname is a reference to function
  • &funcname is a pointer to function

Note that taking the address (or a reference to) a function that is overloaded requires a static_cast to the exact type (to resolve the overload).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.