1

In function.h file I have declared a function as inline such as

inline double foo(int &a)
{

     return a*double value
}

In a.cpp file I have included function.h file and call foo function in many places. a.cpp file also has an instance of class b and I want to call the foo function in b instance. When I call a function in b, I'd like to pass the function pointer to the b so that I can call the foo function in b without including function.h file.

b.cpp file
void b_foo(a function pointer to foo function)
{
     call foo
}

Since I have declared the function as inline, I am not sure if passing the function pointer is efficient rather than just including function.h file in b.cpp.

I'd like to see what might be the difference.

halfer
  • 19,824
  • 17
  • 99
  • 186
codereviewanskquestions
  • 13,460
  • 29
  • 98
  • 167
  • You don't have any classes here, nevermind using a pointer across classes – Ben Voigt Apr 16 '12 at 02:58
  • Talking about what @BenVoigt said: Would it be an idea to change the title of the question into something like "Efficiency loss by using function pointer vs. inlining"? That is what the question is about (..or perhaps actually not?) – jogojapan Apr 16 '12 at 03:03
  • @jogojapan: I think the title should say "in different *compilation unit*". If you agree, let's get it changed. – Ben Voigt Apr 16 '12 at 03:43
  • @BenVoigt I am confused over what the question is ultimately about. Is it about 'How to use a function pointer (in certain circumstances)' or about 'If using a function pointer is more inefficient than using an inline function(in certain circumstances)'. The title suggests the former, the body suggests the latter. – jogojapan Apr 16 '12 at 04:01

4 Answers4

1

Try this:

typedef double (*foo_ptr)(int &);

void b_foo(foo_ptr f)
{
  if (f != NULL) {
    double d = f(5);
  }
}

void f() {
  b_foo(foo);
}

The typedef makes it easier to refer to the pointer-to-function type.

You do not need to dereference the pointer when calling it (you can , but it is not necessary). You also do not need to take the address of the function when passing as parameter (again, you can if you want)

Note that

inline double foo(int &a)  
{  
  return a*double value  
}

is invalid as it has syntax error. Try:

inline double foo(int &a)  
{  
  return a*4.5; 
}

you can declare/use a double local variable as well instead of a double literal

Note: you are talking about functions in instances. If you actually want to call a member function, you need:

typedef double (*B::foo_ptr)(int &);

where B is the class where the function is declared. Then use it this way:

B b;
foo_ptr f = B::foo;
b.*f(5);
Attila
  • 28,265
  • 3
  • 46
  • 55
1

First of all, you're not programming in C. You're programming in C++. It is a different language. C does not have references or classes. In your code you're not using classes but you are using a reference (for no reason).

Second, consider the meaning of "function pointer". It is the address of the code of that function. Now consider the meaning of "inline". It means the function does not exist independently in machine code. Its source is (conceptually) put in the place where it is called and the calling function is compiled. So you want to take the address of something that doesn't exist.

The short answer is you can't.

What do you want to achieve? Do you want to always call foo from b? If so, you don't need an indirection. You can call an inline function and have it inlined into the call site, or you can call a non-inlined function and produce a real function call.

// a.c
double foo(int a) { return a * 3.1415926; }

// b.c
double foo(int a); // declaration, not definition.
void b(void) { printf("%f\n", foo(10)); }
int main() { b(); return 0; }

Build with: gcc -O2 -c -o a.o a.c

Notice that when compiling b.c, the compiler does not know what function foo does, it only knows its signature. gcc -O2 -c -o b.o b.c

This links the two pieces into a single program and adding the parts at the beginning and end that make it possible to run it: gcc -o program a.o b.o

The difference is efficiency. Inlining allows many optimizations (up to using the values of the arguments to precompute the result and eliminate the code entirely, like here). Inlining where such optimizations are impossible can still be faster because it eliminates the function call overhead and can allow better register allocation, as well as making it more likely the code is in cache. But inlining can be bad because it leads to code bloat and cache pollution, making the code less likely to be in cache.

If you don't know at compile time which function you want to call from b, you need indirection. Thus you would have foo_1 and foo_2 and you would pass to b the pointer to either, and it will call the function pointed to by that pointer, without knowing which one it is. This has a performance penalty, but is sometimes necessary.

double foo_1(int a) { return a * 3.1415926; }
double foo_2(int a) { return a * 2.81; }

void b(double (*foo)(int)) { printf("%f\n", foo(10)); }
int main(int argc, char *argv[])
{
  if (argc < 2) return;
  b(argv[1][0]-48 ? &foo_1 : &foo_2);
  return 0;
}

C++ has a feature in which you can tell the compiler to generate two version of function b from the same source code: one that always calls foo_1 and another that always calls foo_2. Then foo_1 and foo_2 can be inlined at both call sites, and instead of choosing to pass the pointer to foo_1 or foo_2 to b you will need to choose to call b_with_foo_1 or b_with_foo_2.

halfer
  • 19,824
  • 17
  • 99
  • 186
Z.T.
  • 939
  • 8
  • 20
  • Instead of just "C++ has a feature", at least tell him the name of that feature is *templates*. And say `b<&foo1>()` rather than `b_with_foo_1`. – Ben Voigt Apr 16 '12 at 03:00
  • I considered that too much information and too far beyond his current needs. I believe OP needs to learn C before doing *any* C++. What I said was the conceptually important part. Syntax is easy. Currently OP does not have trouble with C's syntax but with understanding what it means. If possible, I would suggest to OP to disassemble the generated code to understand what is *really* happening. – Z.T. Apr 16 '12 at 03:02
0

Click here "Pointers To Functions" This maybe helps to you. I dont know but I am new in c. I am sure that you need it.

Jager Note
  • 11
  • 4
0

Whether it makes a real performance difference you can only find out by implementing both versions, turning on compiler optimization and comparing the speed. It depends on too many factors related to the rest of your code to be predictable. It obviously depends in particular on how many times your function is actually called.

But generally speaking, inlining is likely to have a major positive impact on speed.

To keep things flexible, and given that you are apparently using C++ (rather than C), it would be a good idea to use more C++-like ways of dealing with this situation. See this SO post for various possibilities and what they mean. If you follow one of the strategies outlined in the question there, chances are the compiler will inline wherever possible while you still get the flexibility of a function pointer.

Community
  • 1
  • 1
jogojapan
  • 68,383
  • 11
  • 101
  • 131