Correct value type for function pointers in C












0















I was trying to understand function pointers in C. While reading about it on internet (mostly stack overflow QAs) - I came across 2 ways in which I can assign value to a function pointer



#include <stdio.h>

double add(int a, double b) {
return a + b;
}

double subtract(int a, double b) {
return a - b;
}

int main() {
int op_a = 23;
double op_b = 2.9;

// Case 1. Just pass the function (not its address)
double (*math_op)(int a, double b) = add;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

// Case 2. Pass the function's address
math_op = &subtract;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

printf("End of programn");
return 0;
}


I have couple of questions




  1. In the code above - what is the right way to assign value value to function pointer. I see several answers on stack overflow which follow the convention followed in case 1, and I also see some answers following convention in case 2. Both seem to be working correctly for me. Which is one is correct (or preferable)?

  2. Also, in order to call function pointers I see 2 ways in which you can call them - math_op(op_a, op_b) or (*math_op)(op_a, op_b). Again, is there a preferable way of doing this - both seem to be working correctly for me.










share|improve this question























  • It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

    – M.M
    Nov 22 '18 at 21:22











  • !Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

    – chux
    Nov 23 '18 at 3:07
















0















I was trying to understand function pointers in C. While reading about it on internet (mostly stack overflow QAs) - I came across 2 ways in which I can assign value to a function pointer



#include <stdio.h>

double add(int a, double b) {
return a + b;
}

double subtract(int a, double b) {
return a - b;
}

int main() {
int op_a = 23;
double op_b = 2.9;

// Case 1. Just pass the function (not its address)
double (*math_op)(int a, double b) = add;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

// Case 2. Pass the function's address
math_op = &subtract;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

printf("End of programn");
return 0;
}


I have couple of questions




  1. In the code above - what is the right way to assign value value to function pointer. I see several answers on stack overflow which follow the convention followed in case 1, and I also see some answers following convention in case 2. Both seem to be working correctly for me. Which is one is correct (or preferable)?

  2. Also, in order to call function pointers I see 2 ways in which you can call them - math_op(op_a, op_b) or (*math_op)(op_a, op_b). Again, is there a preferable way of doing this - both seem to be working correctly for me.










share|improve this question























  • It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

    – M.M
    Nov 22 '18 at 21:22











  • !Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

    – chux
    Nov 23 '18 at 3:07














0












0








0








I was trying to understand function pointers in C. While reading about it on internet (mostly stack overflow QAs) - I came across 2 ways in which I can assign value to a function pointer



#include <stdio.h>

double add(int a, double b) {
return a + b;
}

double subtract(int a, double b) {
return a - b;
}

int main() {
int op_a = 23;
double op_b = 2.9;

// Case 1. Just pass the function (not its address)
double (*math_op)(int a, double b) = add;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

// Case 2. Pass the function's address
math_op = &subtract;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

printf("End of programn");
return 0;
}


I have couple of questions




  1. In the code above - what is the right way to assign value value to function pointer. I see several answers on stack overflow which follow the convention followed in case 1, and I also see some answers following convention in case 2. Both seem to be working correctly for me. Which is one is correct (or preferable)?

  2. Also, in order to call function pointers I see 2 ways in which you can call them - math_op(op_a, op_b) or (*math_op)(op_a, op_b). Again, is there a preferable way of doing this - both seem to be working correctly for me.










share|improve this question














I was trying to understand function pointers in C. While reading about it on internet (mostly stack overflow QAs) - I came across 2 ways in which I can assign value to a function pointer



#include <stdio.h>

double add(int a, double b) {
return a + b;
}

double subtract(int a, double b) {
return a - b;
}

int main() {
int op_a = 23;
double op_b = 2.9;

// Case 1. Just pass the function (not its address)
double (*math_op)(int a, double b) = add;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

// Case 2. Pass the function's address
math_op = &subtract;
printf("The output of Math Operation %fn", math_op(op_a, op_b));

printf("End of programn");
return 0;
}


I have couple of questions




  1. In the code above - what is the right way to assign value value to function pointer. I see several answers on stack overflow which follow the convention followed in case 1, and I also see some answers following convention in case 2. Both seem to be working correctly for me. Which is one is correct (or preferable)?

  2. Also, in order to call function pointers I see 2 ways in which you can call them - math_op(op_a, op_b) or (*math_op)(op_a, op_b). Again, is there a preferable way of doing this - both seem to be working correctly for me.







c function-pointers






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 '18 at 21:07









NishantNishant

159513




159513













  • It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

    – M.M
    Nov 22 '18 at 21:22











  • !Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

    – chux
    Nov 23 '18 at 3:07



















  • It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

    – M.M
    Nov 22 '18 at 21:22











  • !Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

    – chux
    Nov 23 '18 at 3:07

















It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

– M.M
Nov 22 '18 at 21:22





It doesn't matter, but I would suggest being consistent throughout your code with the method you do choose to go with, not mix and match

– M.M
Nov 22 '18 at 21:22













!Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

– chux
Nov 23 '18 at 3:07





!Nishant Note: posted code lacks a declaration of math_op and a 1st case assignment. Suggest adding these your post for clarity.

– chux
Nov 23 '18 at 3:07












3 Answers
3






active

oldest

votes


















3














I think



Function calls (§6.5.2.2/1):




The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.




is enough to answer both of your questions. The name of a function is implicitly converted to pointer to function type so using the address-of operator when assigning the adress of a function to a function pointer is superfluous. As for calling functions by function pointers the syntax is no different from "ordinary" function calls.






share|improve this answer

































    1














    This is really a quirk of C. The * and (a single) & are kind of ignored when taking an address of a function.



    int main() {
    printf("%p %p %p", (void*)add, (void*)************add, (void*)&add);
    }


    The * are ignored when "dereferencing" a function pointer



    int main() { 
    double (*math_op)(int a, double b) = add;
    printf("%p %p %f", (void*)math_op, (void*)*************math_op, (***************math_op)(1, 1.0));
    }


    It does not matter. However be consistent. Mostly I saw no * nor & used in such contexts.






    share|improve this answer































      0














      Case 1 is preferred.



      The & is optional to take the address of a function (just like: char buf[100]; char *bp = buf;)



      The reason case 1 is preferred is that the syntax is the same for assignment to a function pointer from a function address or another function pointer:



      typedef double (*math_func)(int a, double b);
      math_func math_op = add;
      math_func math_op2 = sub;
      math_func math_op3 = math_op2;


      Analogously, that's why you can say: math_op(2,23) as a shorthand for: (*math_op)(2,23)





      UPDATE:




      Pointer typedefs are not preferred (by me anyway)




      They certainly help for function pointers [which Jonathan Leffler makes an exception for].



      If you had (e.g.) 10 functions that needed to take an argument that was a function pointer, would you want to spell it out in all 10 function prototypes, particularly if the function pointer took 8 arguments itself?



      Suppose [in some API] you had a function pointer:



      typedef void (*funcptr)(int x,int y,int z);


      Consider that you had functions of the form:



      void func(funcptr f,...);


      And, you had a call chain of these functions:



      a -> b -> c -> d -> apiabc


      Functions a-d do not call f--only apiabc does. Only apiabc has knowledge of how to call f properly. The others are merely passing along the opaque [to them] pointer so that apiabc can act on it.



      If funcptr ever had to change, changing a-d would be problematic (i.e. they are not part of the API--merely users of it).



      On pointer typedefs in general, IMO, they are fine if they are reasonably obvious and consistent.



      This would be an example of usages:



      typedef struct node *Node;              // poor
      typedef struct node *pNode; // MS (common but, IMO, poor)
      typedef struct node *nodeP; // okay
      typedef struct node *nodeptr; // better?
      typedef const struct node *nodecptr; // better?


      IMO, the MS version is poor because if we sorted all names pNode would get intermixed with all [unrelated] pWhatever and not gravitate to node whereas looking left to right nodeP has the dominant part first (i.e. it's related to a node).



      IMO, it is hubris for POSIX to lay claim to whatever_t as its province for type names. But, it's low probability that there will be a collision [for me, anyway, because I always use names that are likely to not conflict]. If there is a collision based on a future POSIX type, I lose, and have to change my definitions.



      Thus, my personal conventions are:



      typedef struct node node_t;
      typedef node_t *node_p;
      typedef const node_t *node_pc;


      Any such convention can be used so long as it's applied consistently. In a given set of code, if one encounters foo_p for the first time, yes, one has to look in the .h file for the definition. After that, when one sees bar_p, the convention is already known.



      For me, this usually isn't a problem, because when I encounter an unfamiliar code base, I always look at the definitions in the .h file before looking at code in a .c






      share|improve this answer





















      • 1





        Pointer typedefs are not preferred (by me anyway)

        – M.M
        Nov 22 '18 at 21:32











      • @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

        – Craig Estey
        Nov 22 '18 at 23:28






      • 1





        False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

        – M.M
        Nov 22 '18 at 23:46













      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437993%2fcorrect-value-type-for-function-pointers-in-c%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      I think



      Function calls (§6.5.2.2/1):




      The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.




      is enough to answer both of your questions. The name of a function is implicitly converted to pointer to function type so using the address-of operator when assigning the adress of a function to a function pointer is superfluous. As for calling functions by function pointers the syntax is no different from "ordinary" function calls.






      share|improve this answer






























        3














        I think



        Function calls (§6.5.2.2/1):




        The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.




        is enough to answer both of your questions. The name of a function is implicitly converted to pointer to function type so using the address-of operator when assigning the adress of a function to a function pointer is superfluous. As for calling functions by function pointers the syntax is no different from "ordinary" function calls.






        share|improve this answer




























          3












          3








          3







          I think



          Function calls (§6.5.2.2/1):




          The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.




          is enough to answer both of your questions. The name of a function is implicitly converted to pointer to function type so using the address-of operator when assigning the adress of a function to a function pointer is superfluous. As for calling functions by function pointers the syntax is no different from "ordinary" function calls.






          share|improve this answer















          I think



          Function calls (§6.5.2.2/1):




          The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.




          is enough to answer both of your questions. The name of a function is implicitly converted to pointer to function type so using the address-of operator when assigning the adress of a function to a function pointer is superfluous. As for calling functions by function pointers the syntax is no different from "ordinary" function calls.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 '18 at 22:07

























          answered Nov 22 '18 at 21:19









          SwordfishSwordfish

          1




          1

























              1














              This is really a quirk of C. The * and (a single) & are kind of ignored when taking an address of a function.



              int main() {
              printf("%p %p %p", (void*)add, (void*)************add, (void*)&add);
              }


              The * are ignored when "dereferencing" a function pointer



              int main() { 
              double (*math_op)(int a, double b) = add;
              printf("%p %p %f", (void*)math_op, (void*)*************math_op, (***************math_op)(1, 1.0));
              }


              It does not matter. However be consistent. Mostly I saw no * nor & used in such contexts.






              share|improve this answer




























                1














                This is really a quirk of C. The * and (a single) & are kind of ignored when taking an address of a function.



                int main() {
                printf("%p %p %p", (void*)add, (void*)************add, (void*)&add);
                }


                The * are ignored when "dereferencing" a function pointer



                int main() { 
                double (*math_op)(int a, double b) = add;
                printf("%p %p %f", (void*)math_op, (void*)*************math_op, (***************math_op)(1, 1.0));
                }


                It does not matter. However be consistent. Mostly I saw no * nor & used in such contexts.






                share|improve this answer


























                  1












                  1








                  1







                  This is really a quirk of C. The * and (a single) & are kind of ignored when taking an address of a function.



                  int main() {
                  printf("%p %p %p", (void*)add, (void*)************add, (void*)&add);
                  }


                  The * are ignored when "dereferencing" a function pointer



                  int main() { 
                  double (*math_op)(int a, double b) = add;
                  printf("%p %p %f", (void*)math_op, (void*)*************math_op, (***************math_op)(1, 1.0));
                  }


                  It does not matter. However be consistent. Mostly I saw no * nor & used in such contexts.






                  share|improve this answer













                  This is really a quirk of C. The * and (a single) & are kind of ignored when taking an address of a function.



                  int main() {
                  printf("%p %p %p", (void*)add, (void*)************add, (void*)&add);
                  }


                  The * are ignored when "dereferencing" a function pointer



                  int main() { 
                  double (*math_op)(int a, double b) = add;
                  printf("%p %p %f", (void*)math_op, (void*)*************math_op, (***************math_op)(1, 1.0));
                  }


                  It does not matter. However be consistent. Mostly I saw no * nor & used in such contexts.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 22 '18 at 21:27









                  Kamil CukKamil Cuk

                  12k1529




                  12k1529























                      0














                      Case 1 is preferred.



                      The & is optional to take the address of a function (just like: char buf[100]; char *bp = buf;)



                      The reason case 1 is preferred is that the syntax is the same for assignment to a function pointer from a function address or another function pointer:



                      typedef double (*math_func)(int a, double b);
                      math_func math_op = add;
                      math_func math_op2 = sub;
                      math_func math_op3 = math_op2;


                      Analogously, that's why you can say: math_op(2,23) as a shorthand for: (*math_op)(2,23)





                      UPDATE:




                      Pointer typedefs are not preferred (by me anyway)




                      They certainly help for function pointers [which Jonathan Leffler makes an exception for].



                      If you had (e.g.) 10 functions that needed to take an argument that was a function pointer, would you want to spell it out in all 10 function prototypes, particularly if the function pointer took 8 arguments itself?



                      Suppose [in some API] you had a function pointer:



                      typedef void (*funcptr)(int x,int y,int z);


                      Consider that you had functions of the form:



                      void func(funcptr f,...);


                      And, you had a call chain of these functions:



                      a -> b -> c -> d -> apiabc


                      Functions a-d do not call f--only apiabc does. Only apiabc has knowledge of how to call f properly. The others are merely passing along the opaque [to them] pointer so that apiabc can act on it.



                      If funcptr ever had to change, changing a-d would be problematic (i.e. they are not part of the API--merely users of it).



                      On pointer typedefs in general, IMO, they are fine if they are reasonably obvious and consistent.



                      This would be an example of usages:



                      typedef struct node *Node;              // poor
                      typedef struct node *pNode; // MS (common but, IMO, poor)
                      typedef struct node *nodeP; // okay
                      typedef struct node *nodeptr; // better?
                      typedef const struct node *nodecptr; // better?


                      IMO, the MS version is poor because if we sorted all names pNode would get intermixed with all [unrelated] pWhatever and not gravitate to node whereas looking left to right nodeP has the dominant part first (i.e. it's related to a node).



                      IMO, it is hubris for POSIX to lay claim to whatever_t as its province for type names. But, it's low probability that there will be a collision [for me, anyway, because I always use names that are likely to not conflict]. If there is a collision based on a future POSIX type, I lose, and have to change my definitions.



                      Thus, my personal conventions are:



                      typedef struct node node_t;
                      typedef node_t *node_p;
                      typedef const node_t *node_pc;


                      Any such convention can be used so long as it's applied consistently. In a given set of code, if one encounters foo_p for the first time, yes, one has to look in the .h file for the definition. After that, when one sees bar_p, the convention is already known.



                      For me, this usually isn't a problem, because when I encounter an unfamiliar code base, I always look at the definitions in the .h file before looking at code in a .c






                      share|improve this answer





















                      • 1





                        Pointer typedefs are not preferred (by me anyway)

                        – M.M
                        Nov 22 '18 at 21:32











                      • @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                        – Craig Estey
                        Nov 22 '18 at 23:28






                      • 1





                        False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                        – M.M
                        Nov 22 '18 at 23:46


















                      0














                      Case 1 is preferred.



                      The & is optional to take the address of a function (just like: char buf[100]; char *bp = buf;)



                      The reason case 1 is preferred is that the syntax is the same for assignment to a function pointer from a function address or another function pointer:



                      typedef double (*math_func)(int a, double b);
                      math_func math_op = add;
                      math_func math_op2 = sub;
                      math_func math_op3 = math_op2;


                      Analogously, that's why you can say: math_op(2,23) as a shorthand for: (*math_op)(2,23)





                      UPDATE:




                      Pointer typedefs are not preferred (by me anyway)




                      They certainly help for function pointers [which Jonathan Leffler makes an exception for].



                      If you had (e.g.) 10 functions that needed to take an argument that was a function pointer, would you want to spell it out in all 10 function prototypes, particularly if the function pointer took 8 arguments itself?



                      Suppose [in some API] you had a function pointer:



                      typedef void (*funcptr)(int x,int y,int z);


                      Consider that you had functions of the form:



                      void func(funcptr f,...);


                      And, you had a call chain of these functions:



                      a -> b -> c -> d -> apiabc


                      Functions a-d do not call f--only apiabc does. Only apiabc has knowledge of how to call f properly. The others are merely passing along the opaque [to them] pointer so that apiabc can act on it.



                      If funcptr ever had to change, changing a-d would be problematic (i.e. they are not part of the API--merely users of it).



                      On pointer typedefs in general, IMO, they are fine if they are reasonably obvious and consistent.



                      This would be an example of usages:



                      typedef struct node *Node;              // poor
                      typedef struct node *pNode; // MS (common but, IMO, poor)
                      typedef struct node *nodeP; // okay
                      typedef struct node *nodeptr; // better?
                      typedef const struct node *nodecptr; // better?


                      IMO, the MS version is poor because if we sorted all names pNode would get intermixed with all [unrelated] pWhatever and not gravitate to node whereas looking left to right nodeP has the dominant part first (i.e. it's related to a node).



                      IMO, it is hubris for POSIX to lay claim to whatever_t as its province for type names. But, it's low probability that there will be a collision [for me, anyway, because I always use names that are likely to not conflict]. If there is a collision based on a future POSIX type, I lose, and have to change my definitions.



                      Thus, my personal conventions are:



                      typedef struct node node_t;
                      typedef node_t *node_p;
                      typedef const node_t *node_pc;


                      Any such convention can be used so long as it's applied consistently. In a given set of code, if one encounters foo_p for the first time, yes, one has to look in the .h file for the definition. After that, when one sees bar_p, the convention is already known.



                      For me, this usually isn't a problem, because when I encounter an unfamiliar code base, I always look at the definitions in the .h file before looking at code in a .c






                      share|improve this answer





















                      • 1





                        Pointer typedefs are not preferred (by me anyway)

                        – M.M
                        Nov 22 '18 at 21:32











                      • @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                        – Craig Estey
                        Nov 22 '18 at 23:28






                      • 1





                        False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                        – M.M
                        Nov 22 '18 at 23:46
















                      0












                      0








                      0







                      Case 1 is preferred.



                      The & is optional to take the address of a function (just like: char buf[100]; char *bp = buf;)



                      The reason case 1 is preferred is that the syntax is the same for assignment to a function pointer from a function address or another function pointer:



                      typedef double (*math_func)(int a, double b);
                      math_func math_op = add;
                      math_func math_op2 = sub;
                      math_func math_op3 = math_op2;


                      Analogously, that's why you can say: math_op(2,23) as a shorthand for: (*math_op)(2,23)





                      UPDATE:




                      Pointer typedefs are not preferred (by me anyway)




                      They certainly help for function pointers [which Jonathan Leffler makes an exception for].



                      If you had (e.g.) 10 functions that needed to take an argument that was a function pointer, would you want to spell it out in all 10 function prototypes, particularly if the function pointer took 8 arguments itself?



                      Suppose [in some API] you had a function pointer:



                      typedef void (*funcptr)(int x,int y,int z);


                      Consider that you had functions of the form:



                      void func(funcptr f,...);


                      And, you had a call chain of these functions:



                      a -> b -> c -> d -> apiabc


                      Functions a-d do not call f--only apiabc does. Only apiabc has knowledge of how to call f properly. The others are merely passing along the opaque [to them] pointer so that apiabc can act on it.



                      If funcptr ever had to change, changing a-d would be problematic (i.e. they are not part of the API--merely users of it).



                      On pointer typedefs in general, IMO, they are fine if they are reasonably obvious and consistent.



                      This would be an example of usages:



                      typedef struct node *Node;              // poor
                      typedef struct node *pNode; // MS (common but, IMO, poor)
                      typedef struct node *nodeP; // okay
                      typedef struct node *nodeptr; // better?
                      typedef const struct node *nodecptr; // better?


                      IMO, the MS version is poor because if we sorted all names pNode would get intermixed with all [unrelated] pWhatever and not gravitate to node whereas looking left to right nodeP has the dominant part first (i.e. it's related to a node).



                      IMO, it is hubris for POSIX to lay claim to whatever_t as its province for type names. But, it's low probability that there will be a collision [for me, anyway, because I always use names that are likely to not conflict]. If there is a collision based on a future POSIX type, I lose, and have to change my definitions.



                      Thus, my personal conventions are:



                      typedef struct node node_t;
                      typedef node_t *node_p;
                      typedef const node_t *node_pc;


                      Any such convention can be used so long as it's applied consistently. In a given set of code, if one encounters foo_p for the first time, yes, one has to look in the .h file for the definition. After that, when one sees bar_p, the convention is already known.



                      For me, this usually isn't a problem, because when I encounter an unfamiliar code base, I always look at the definitions in the .h file before looking at code in a .c






                      share|improve this answer















                      Case 1 is preferred.



                      The & is optional to take the address of a function (just like: char buf[100]; char *bp = buf;)



                      The reason case 1 is preferred is that the syntax is the same for assignment to a function pointer from a function address or another function pointer:



                      typedef double (*math_func)(int a, double b);
                      math_func math_op = add;
                      math_func math_op2 = sub;
                      math_func math_op3 = math_op2;


                      Analogously, that's why you can say: math_op(2,23) as a shorthand for: (*math_op)(2,23)





                      UPDATE:




                      Pointer typedefs are not preferred (by me anyway)




                      They certainly help for function pointers [which Jonathan Leffler makes an exception for].



                      If you had (e.g.) 10 functions that needed to take an argument that was a function pointer, would you want to spell it out in all 10 function prototypes, particularly if the function pointer took 8 arguments itself?



                      Suppose [in some API] you had a function pointer:



                      typedef void (*funcptr)(int x,int y,int z);


                      Consider that you had functions of the form:



                      void func(funcptr f,...);


                      And, you had a call chain of these functions:



                      a -> b -> c -> d -> apiabc


                      Functions a-d do not call f--only apiabc does. Only apiabc has knowledge of how to call f properly. The others are merely passing along the opaque [to them] pointer so that apiabc can act on it.



                      If funcptr ever had to change, changing a-d would be problematic (i.e. they are not part of the API--merely users of it).



                      On pointer typedefs in general, IMO, they are fine if they are reasonably obvious and consistent.



                      This would be an example of usages:



                      typedef struct node *Node;              // poor
                      typedef struct node *pNode; // MS (common but, IMO, poor)
                      typedef struct node *nodeP; // okay
                      typedef struct node *nodeptr; // better?
                      typedef const struct node *nodecptr; // better?


                      IMO, the MS version is poor because if we sorted all names pNode would get intermixed with all [unrelated] pWhatever and not gravitate to node whereas looking left to right nodeP has the dominant part first (i.e. it's related to a node).



                      IMO, it is hubris for POSIX to lay claim to whatever_t as its province for type names. But, it's low probability that there will be a collision [for me, anyway, because I always use names that are likely to not conflict]. If there is a collision based on a future POSIX type, I lose, and have to change my definitions.



                      Thus, my personal conventions are:



                      typedef struct node node_t;
                      typedef node_t *node_p;
                      typedef const node_t *node_pc;


                      Any such convention can be used so long as it's applied consistently. In a given set of code, if one encounters foo_p for the first time, yes, one has to look in the .h file for the definition. After that, when one sees bar_p, the convention is already known.



                      For me, this usually isn't a problem, because when I encounter an unfamiliar code base, I always look at the definitions in the .h file before looking at code in a .c







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 22 '18 at 23:24

























                      answered Nov 22 '18 at 21:27









                      Craig EsteyCraig Estey

                      15.2k21130




                      15.2k21130








                      • 1





                        Pointer typedefs are not preferred (by me anyway)

                        – M.M
                        Nov 22 '18 at 21:32











                      • @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                        – Craig Estey
                        Nov 22 '18 at 23:28






                      • 1





                        False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                        – M.M
                        Nov 22 '18 at 23:46
















                      • 1





                        Pointer typedefs are not preferred (by me anyway)

                        – M.M
                        Nov 22 '18 at 21:32











                      • @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                        – Craig Estey
                        Nov 22 '18 at 23:28






                      • 1





                        False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                        – M.M
                        Nov 22 '18 at 23:46










                      1




                      1





                      Pointer typedefs are not preferred (by me anyway)

                      – M.M
                      Nov 22 '18 at 21:32





                      Pointer typedefs are not preferred (by me anyway)

                      – M.M
                      Nov 22 '18 at 21:32













                      @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                      – Craig Estey
                      Nov 22 '18 at 23:28





                      @M.M Granted, this is a bit of personal style/preference. I've added an update to my answer (too long for a comment) that lays out how I use pointer typedefs and why. See what you think ...

                      – Craig Estey
                      Nov 22 '18 at 23:28




                      1




                      1





                      False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                      – M.M
                      Nov 22 '18 at 23:46







                      False dichotomy, you compare pointer typedef with not using typedef at all... I would use a non-pointer typedef. typedef double math_func(int a, double b); math_func add, sub; /* ... */ math_func *math_op = add;. Later on you recommend node_p with the comment "one has to look in the .h file for the definition". However if you just used node_t * then nothing needs to be looked up

                      – M.M
                      Nov 22 '18 at 23:46




















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437993%2fcorrect-value-type-for-function-pointers-in-c%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                      Alcedinidae

                      Can an atomic nucleus contain both particles and antiparticles? [duplicate]