3

I understand that similar questions with answers have been asked before. I already understand the concept of a function pointer and the meaning of its declaration. Following is my sample code of a function's pointer, where I assign the function pointer fp_GetBiggerElement to point to the function GetBiggerElement

    #include <iostream>

    typedef     int     (*fp_GetBiggerElement)      (int, int);
    //           ^                ^                     ^
    //      return type      type name              arguments

    using namespace std;

    int GetBiggerElement(int arg1, int arg2)
    {
        int bigger = arg1 > arg2 ? arg1 : arg2;
        return bigger;
    }

    int main()
    {
        fp_GetBiggerElement funcPtr = GetBiggerElement;

        int valueReturned = funcPtr(10, 20);
        cout << valueReturned << endl;
        return 0;
    }

What I understand is, typedef means to assing a new definition for a type. Usually, the typedef statement needs two-parts(or say two-arguments)

  1. first part is the type which needs a new alias

  2. second part is a new alias name

    typedef     unsigned  int       UnsignedInt;
    //              ^                   ^                       
    //          (original type)     (Alias)
    

for example, in the code above, the first part is unsigned int and the second part is UnsignedInt

    typedef     char *              CharPtr;
    //              ^                   ^                       
    //      (original type)          (Alias)

similarly, in the second example above, the first part is char* and the second part is CharPtr

QUESTION: I am confused with the FORMAT of the typedef statement for a function pointer. In the statement typedef int(*fp_GetBiggerElement)(int, int);, the typical two-arguments format for typedef is not followed then, how is it working?

UPDATE: I am aware that C++11 offers another way of declaring function pointer i.e. (by using statment). In this question, I am only interested to understand the syntax of typedef statement for a fucntion pointer.

skm
  • 5,015
  • 8
  • 43
  • 104
  • Possible duplicate: https://stackoverflow.com/q/4295432/253056 – Paul R Oct 15 '19 at 08:19
  • 1
    @PaulR: That's the same question whose link I have posted in my OP but it doesn't answer to my question. – skm Oct 15 '19 at 08:21
  • @skm To be more precise, it's not the syntax of `typedef`, it's the syntax of a function pointer that is different. The function pointer syntax looks the same everywhere. In declarations and in typedefs. – super Oct 15 '19 at 08:28
  • @bloody Not necessarily. Explicitly taking the address of a function is just as legal as using the function name directly (some prefer to show intention more clearly). Be aware that for member functions, you *must* use the address-of operator! – Aconcagua Oct 15 '19 at 08:28
  • @Aconcagua Oh, thanks, never encountered such (for member functions I know). I deleted that comment. – bloody Oct 15 '19 at 08:43

5 Answers5

6

I think the best idea to think about typedef syntax is like declaring variable of type you want to typedef. For example:

char *CharPtr;// declare CharPtr to be variable of type char*

typedef char *CharPtr_t;// declare CharPtr_t to be alias of type char*

Similarly with function pointers:

int (*fp) (int, int);// declare fp as pointer to int(int, int)

typedef int (*fp_t)(int, int);// declare fp_t to be alias of pointer to int(int, int)

Btw, in C++11 and further you get not-so-confusing (and more powerful) alternative to typedef - using. You should be using (pun intended) it instead. Just look:

using fp = int (*)(int, int);// declare fp_t to be alias of pointer to int(int, int)
bartop
  • 9,971
  • 1
  • 23
  • 54
4

typedef uses the same syntax as a variable declaration, but declares a type name rather than a variable name.

The parts are "intermingled" in a somewhat peculiar (some would call it "wtf?") way - a variable declaration has the same form as its use, which simplifies the parser and enables reusing code in the compiler.

It makes more sense if you read in a more "old-school" way:

int *p;

"*p is an int"
(Equivalent translation: "p is a pointer to int")

int *p, x;

"*p and x are both ints"
("p is a pointer to int, and x is an int")

int (*q)[3];

"*q is an array of three ints", or "(*q)[x] is an int"
("q is a pointer to an array of three ints")

int (*fp)(int,int);

"*fp is a function that takes two ints and returns an int"
("fp is a pointer to a function that takes two ints and returns an int")

int (*(*foo)())[3];

"*(*foo)() is an array of three ints" (alternatively, "(*(*foo)())[x] is an int) - or, in other words,
"(*foo)() is a pointer to an array of three ints" - or, in other words,
"foo is a pointer to a function that takes no arguments and returns a pointer to an array of three ints"

A slightly unreadable effect of this is that

int *p, x, (*q)[3], (*fp)(int,int), (*(*foo)())[3];

declares all of the above at once.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
3

That's just the syntax for function pointers. You would see the same thing if you just declare a variable.

int foo; // Normal
int (*bar)(int, int); // bar is of type int(*)(int,int)

Personally i prefer to use using = ... which in my opinion is more clear.

using fp_GetBiggerElement = int (*)(int,int);
super
  • 12,335
  • 2
  • 19
  • 29
1

This syntax comes from the C-way of reading variables.

Ever wondered why we need an asterisk, for every pointer we want to declare in a single expression?

int *p1, *p2, p3; // p3 is not a pointer

C++ people generally tend to see a variable having a specific type, which can be a pointer (in other words, they see the pointer characteristics as property of the type). That's why they usually prefer writing

int* p1; // notice asterisk grouped with type

C people rather read as: I have a variable p1, and if I dereference it, I get type int (so p1 being a pointer is deduced information, i. e. they see the pointer characteristics rather as property of the variable; and that's why they rather group the asterisk to the name: int *p1;).

Pretty similar for function pointers:

int (*fp) (int, int);

I have a variable fp, and if I dereference it, I get int (int, int). Same pattern then for the typedef. On the other hand, the (new) C++ way for defining an alias reflects much better the C++ way of thinking:

using fp = int (*)(int, int);

I have a variable, and it's type is a pointer (to whatever) right from the start – well, not fully consistently, though: With C++ way of thinking, function pointers might rather look like int(int, int)* or maybe requiring parentheses (int(int, int))*, but OK, that's not the way it is (wanting to stay compatible with C being reason for).

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
0

typedef declarations are similar to simple declarations but instead of declaring an identifier of a derclarator as an identifier of an object or a function they declare an identifier of a declarator as an alias for the specified type.

Consider the following examples of simple declarations

int x;
unsigned int a[10][20];
int unsigned ( *p )[10][20];
void ( *f )( int, int );
double h( double ); 

They declare several objects and the function h.

Now place in these declarations decl-specifier typedef (in any order relative to other decl-specifiers) and you will get that the declared identifiers become aliases of types.

typedef int x;
unsigned typedef int a[10][20];
int unsigned typedef ( *p )[10][20];
void typedef ( *f )( int, int );
typedef double h( double ); 

That is x is an alias of the type int. a is an alias for the type unsigned int [10][20]. p is an alias for the pointer type unsigned int ( * )[10][20]. f is an alias for the function pointer void ( * )( int, int ). And h in an alias for the function type double( double ).

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335