1
CUnknown* (*)( LPUNKNOWN pUnk, HRESULT* phr );

Seems I've always been in trouble reading such complicated pointers..

How do you read it? what if the expression even longer?

Yacoby
  • 54,544
  • 15
  • 116
  • 120
Alan
  • 5,029
  • 5
  • 32
  • 37

7 Answers7

3

Everyone has said what it is, but you asked how to read it.

Function pointer syntax is as follows:

RETURN_VALUE (*POINTER_NAME) (ARGUMENT LIST)

So

foo (*bar) (baz)

is a pointer to a function taking baz and returning foo, and the pointer is called bar.

In the case that you only want to write the type of a function pointer, rather than declare one, you just leave out the name, e.g.

RETURN_VALUE (*) (ARGUMENT_LIST)

as you see here.

For parsing hard-to-understand C declarations, there's a nice program called cdecl available on most Linux and Unix-like systems, as well as available as a web app: http://cdecl.org/

Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
  • What if it's `CUnknown* (***)( LPUNKNOWN pUnk, HRESULT* phr );` ? is that valid any more? – Alan Aug 18 '10 at 13:51
  • @Alan: `***` is valid. It declares pointer to pointer to pointer to function. – jfs Aug 18 '10 at 13:56
  • cdecl.org gives error syntax as result both for your question and for your original statement. – Adriano Varoli Piazza Aug 18 '10 at 13:57
  • Yes, that's a pointer-to-pointer-to-pointer-to-function with the given arguments and return value, much like `int***` is a pointer-to-pointer-to-pointer-to-int. – Tyler McHenry Aug 18 '10 at 13:58
  • @Alan: http://cdecl.ridiculousfish.com/?q=double%2A+%28%2A%2A%2Af%29%28+char%2A+%2C+int%2A+%29%3B – jfs Aug 18 '10 at 13:58
  • @Adriano It's because really you're not supposed to give *names* to the parameters in a function pointer declaration, just types. I'm not not sure if the C standard *forbids* giving names, but cdecl doesn't like it. – Tyler McHenry Aug 18 '10 at 13:58
  • @Tyler: I'm not blaming you, but would be helpful to have some kind of help in the site. * (***)( int, * ); fails too, and other combos do too. – Adriano Varoli Piazza Aug 18 '10 at 14:05
  • I see that it only seems to accept standard types. An accepted decl is `int* (***f)( char* , int* )` – Adriano Varoli Piazza Aug 18 '10 at 14:07
3

What I learned from books and Uni was to start at the middle and proceed outwards back and forth. The trick is only to do it slowly, and know where the middle actually is.

You have a

CUnknown* (*)( LPUNKNOWN pUnk, HRESULT* phr );

that's a pointer (*)

Now we go right: it's a pointer to a function because the next thing is a (

The arguments of the function are a LPUNKNOWN and a pointer to HRESULT, and that's it.

Now we go left: the function returns a pointer to CUnknown.

So, as stated by everyone, it's a pointer to a function that takes two arguments -a LPUNKNOWN and a pointer to a HRESULT- and returns a pointer to CUnknown.

Link beauties: this and this.

Community
  • 1
  • 1
Adriano Varoli Piazza
  • 7,297
  • 5
  • 39
  • 50
1

The Clockwise Spiral Rule helps me understand things like this. From the site:

  1. Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
  2. Keep doing this in a spiral/clockwise direction until all tokens have been covered.

  3. Always resolve anything in parenthesis first!

    [X] or []

=> Array X size of... or Array undefined size of...

(type1, type2)

=> function passing type1 and type2 returning...

*

=> pointer(s) to...

Jamison Dance
  • 19,896
  • 25
  • 97
  • 99
0

It's a pointer to a function taking the arguments 'LPUNKNOWN pUnk, HRESULT* phr' and it returns a pointer to a CUnknown.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
0

it's a function pointer with two arguments that returns a CUnknown*

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
0

I think this is pointer to a function taking LPUNKNOWN and pointer to HRESULT, returning pointer to CUnknown

Piotr Müller
  • 5,323
  • 5
  • 55
  • 82
0

For some function:

int f(int a, int& b, int* c);

The type of the expression:

&f

Or, equivalently:

f

Is:

int(*)(int, int&, int*)

And an easy way to remember this is that a function pointer type specifier is just like a function declaration, except with the name replaced with (*). You can also perform a typedef:

typedef int(*ftype)(int, int&, int*);

And now you can write:

ftype func = f;

Rather than:

int(*func)(int, int&, int*) = f;
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166