0

I don't know how right to call function through pointer.

For example i have this pointer: int (*ptr)() = a_function;

To call a function i must write something like this ptr() or (*ptr)()

What is the difference between these calls? If i write printf("%p - %p", ptr, *ptr) I will get an address in the both cases

MaximPro
  • 563
  • 8
  • 21
  • The correct answer is `(***ptr)()` if you're a three-star programmer, or `(*****ptr)()` if you're really good. Also, you should have said `(***printf)("%p - %p", ptr, *ptr)`. – Kerrek SB Feb 04 '17 at 22:12
  • hahaha nice joke, but i want to get the answer – MaximPro Feb 04 '17 at 22:13
  • 2
    There is no difference in behaviour or meaning. – Kerrek SB Feb 04 '17 at 22:14
  • 1
    [This thread](http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen) might be helpful. – dhrumeel Feb 04 '17 at 22:16
  • Note: The `%p` conversion type specifier requires a `void *`, which is a object pointer. Functions are not object in C, thus your code invokes undefined behaviour. Many architectures allow to cast a function pointer to `void *`, but you have to do this like for any other pointer explicitly (this is actually a rare occasion you have to cast to `void *`. – too honest for this site Feb 04 '17 at 22:46
  • Doing `ptr` gives you the function pointer's value. Doing `ptr()` calls the function the function pointer points to. Mind the parenthesis. – alk Feb 05 '17 at 11:38

3 Answers3

0

Either works.

This is because when you use a function in an expression, it immediately decays to a pointer - unless it's the operand of &, in which case you get a pointer to the function anyway.

So when you write something like printf("hi"), you have the function call operator () with two operands: printf, and an argument list consisting of one value, "hi".

printf is a function and it's not the operand of &, so what the function call operator () actually gets is a function pointer. That's why ptr() works in your example: Function calls are defined to work with function pointers anyway.

So what about (*ptr)()? Well, ptr is a function pointer and you can dereference it to get the function ... which immediately decays back to a pointer, so it can be used with () to call it.

The same thing applies to printf (or any other function). (*printf)() is valid for almost the same reason: printf decays to a function pointer, which gets dereferenced by * to a function, which immediately decays to a pointer again.

melpomene
  • 84,125
  • 8
  • 85
  • 148
0

A value of function type decays to a value of type pointer-to-function in many contexts, similar to how values of array type decay to pointers to the first element of the array.

A function call expression is the postfix expression E(...), where E is an expression of either function or pointer-to-function type. This means that a variety of call syntaxes are valid, and all mean the same thing:

void f(void);
void (*p)(void) = &f;

f();        // "f" is an expression of function type
p();        // "p" is an expression of pointer-to-function type

(*p)();     // *p is a function
(*f)();     // "f" decays to a pointer, "*f" dereferences that pointer
(****f)();  // like above, but continue decay and deref
(****p)();  // ditto
(**&f)();   // why not

Incidentally, one of the contexts in which no decay occurs is as the operand of the address-of operator: So in &f, f does not decay, but denotes the actual function, whose address is taken. Alternatively, when you write p = f;, you use the implicit decay of f to &f.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

C has some magic built-in involving the equivalence of pointers and functions, and the equivalence of pointers and arrays. For that reason, you can sometimes "get away" with not spelling out the full dereference of a pointer when it points to an array or a function.

However, I'd like to point out (ahem, see what I did there?) that one of the design goals of C type declarations is that the declaration of an object and the use of that object are the same.

For example:

int   *p;   // p is a pointer to int

Now, how do I get an int?

int y =    /* wait for it ... */   *p;

Similarly,

float *****p[2];

float y =   *****p[0]; // or [1]

So, if you have this declaration:

 int (*ptr)() = a_function;

Then let's ask the question, "How can you get an int?" Which is to say, how can you invoke the pointer-to-function-taking-no-args-returning-int? The answer is to replicate what you have already declared:

 int y = (*ptr)();

Yes, you could say "ptr is a pointer, and there is a magic equivalence between functions and pointer-to-functions, to p() will work". But don't. Because right now, you aren't confident enough to do that. So just trust that for whatever C declaration, if you want to get the type on the very left, all you need to do is use the *'s and []'s and ()'s on the right, and you'll get there.

aghast
  • 14,785
  • 3
  • 24
  • 56