typedef procedure

Discussion in 'C Programming' started by aleksa, May 10, 2010.

  1. aleksa

    aleksa Guest

    typedef void (*PROC) (void); // v1
    typedef void (PROC) (void); // v2

    void foo (PROC callme)
    {
    callme();
    }

    Do I use V1 or V2 when defining PROC?
    Both seem to work...

    TIA
    aleksa, May 10, 2010
    #1
    1. Advertising

  2. aleksa

    John Bode Guest

    On May 10, 7:53 am, "BGB / cr88192" <> wrote:
    > "Richard Heathfield" <> wrote in message
    >
    > news:...
    >
    >
    >
    >
    >
    > > aleksa wrote:
    > >> typedef void (*PROC) (void); // v1
    > >> typedef void  (PROC) (void); // v2

    >
    > >> void foo (PROC callme)
    > >> {
    > >>     callme();
    > >> }

    >
    > >> Do I use V1 or V2 when defining PROC?

    >
    > > I'd do it this way:

    >
    > > typedef void PROC(void);

    >
    > > void foo(PROC *callme)
    > > {
    > >   (*callme)();
    > > }

    >
    > > This way avoids hiding the pointeriness of callme behind a typedef.

    >
    > but, this form looks more ugly...
    >
    > there is no reason to make things more ugly than they need to be...
    >
    > we could just as easily imagine that this were some-other-language, where
    > functions typically are first-class, and most objects are reference-types
    > without explicit pointer marks...
    >
    > then, there is no confusion about the function pointer, they just take
    > something and call it...- Hide quoted text -
    >
    > - Show quoted text -


    Bitter experience has taught me that hiding a pointer behind a typedef
    inevitably leads to heartburn[1]. Eventually someone forgets they're
    dealing with a pointer type and tries to use '&' when they don't need
    to, or attempts to use '.' when they meant '->', or forgets that they
    need to use '*' before passing it to another function, etc. Unless
    it's something you will never have to dereference (either explicitly
    with * or implicitly with -> or []), then IME it's best to explicitly
    declare the object as a pointer.

    1. In C, anyway; I am slowly learning that C++ is a very different
    animal in this regard, especially when it comes to writing templates,
    although I've seen this same problem bite other people in the ass in C+
    +.
    John Bode, May 10, 2010
    #2
    1. Advertising

  3. "aleksa" <> writes:

    > typedef void (*PROC) (void); // v1
    > typedef void (PROC) (void); // v2
    >
    > void foo (PROC callme)
    > {
    > callme();
    > }
    >
    > Do I use V1 or V2 when defining PROC?
    > Both seem to work...


    They do, yes. I'd go a third way! The trouble with v1 is that is hides
    the fact the PROC is a pointer type. Many people have found that this
    can be troublesome later, but it is fair to say that it is at its "least
    bad" with function types because there is so little you can do with
    them. None the less, I'd use v2 but without ALL CAPS (all caps is for
    MACROS in my book) and without the extra parentheses:

    typedef void Proc(void);

    However, I'd then write:

    void foo (Proc *callme)
    {
    callme();
    }

    so that the fact that a pointer is being passed is obvious. Function
    types in parameter lists are converted to pointer-to-function types but
    it's clearer, in my view, if you make the pointer explicit.

    I learnt C when one had to write (*callme)() but I've grown to prefer
    callme().

    --
    Ben.
    Ben Bacarisse, May 10, 2010
    #3
  4. pete <> writes:
    > aleksa wrote:
    >> typedef void (*PROC) (void); // v1
    >> typedef void (PROC) (void); // v2
    >>
    >> void foo (PROC callme)
    >> {
    >> callme();
    >> }
    >>
    >> Do I use V1 or V2 when defining PROC?
    >> Both seem to work...

    >
    > It's analagous to the difference between
    > void foo(char *array);
    > and
    > void foo(char array[]);


    Yes, it is ...

    > The only thing that you can do with an expression of function type
    > in statement in a correct C program, is to derive a pointer from it.
    >
    > An expression of function type will always convert to pointer,
    > unless it is the operand of the adress operator,
    > in which case the result is a pointer,
    > or unless it is the operand of the sizeof operator,
    > in which case you do not have a correct C program.


    .... but not for that reason. As with arrays and pointers, there are two
    independent rules regarding functions and pointers. One rule is about
    the compile-time meaning of a parameter declaration; the other is about
    implicit conversion of expressions of function type.

    C99 6.7.5.3p7:

    A declaration of a parameter as ‘‘array of _type_’’ shall be adjusted
    to ‘‘qualified pointer to _type_’’, [...]

    and p8:

    A declaration of a parameter as ‘‘function returning _type_’’ shall
    be adjusted to ‘‘pointer to function returning _type_’’, [...]

    C99 6.3.2.1p3:

    Except when [exceptions skipped], an expression that has type
    ‘‘array of _type_’’ is converted to an expression with type
    ‘‘pointer to _type_’’ that points to the initial element of the
    array object and is not an lvalue.

    and p4:

    A _function designator_ is an expression that has function
    type. Except when it is the operand of the sizeof operator or the
    unary & operator, a function designator with type ‘‘function
    returning type’’ is converted to an expression that has type
    ‘‘pointer to function returning type’’.

    It's 6.7.5.3, not 6.3.2.1, that applies to the OP's code.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, May 10, 2010
    #4
  5. aleksa

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > "aleksa" <> writes:
    >
    >> typedef void (*PROC) (void); // v1
    >> typedef void (PROC) (void); // v2
    >>
    >> void foo (PROC callme)
    >> {
    >> callme();
    >> }
    >>
    >> Do I use V1 or V2 when defining PROC?
    >> Both seem to work...

    >
    > They do, yes. I'd go a third way! The trouble with v1 is that is hides
    > the fact the PROC is a pointer type. Many people have found that this
    > can be troublesome later, but it is fair to say that it is at its "least
    > bad" with function types because there is so little you can do with
    > them. None the less, I'd use v2 but without ALL CAPS (all caps is for
    > MACROS in my book) and without the extra parentheses:
    >
    > typedef void Proc(void);
    >
    > However, I'd then write:
    >
    > void foo (Proc *callme)
    > {
    > callme();
    > }
    >
    > so that the fact that a pointer is being passed is obvious. Function
    > types in parameter lists are converted to pointer-to-function types but
    > it's clearer, in my view, if you make the pointer explicit.


    I understand you're expressing what is in essence just a personal
    opinion. Still I would like to ask for some amount of explanation
    or elaboration. Personally I don't see any value to using 'Foo *f'
    instead of 'Foo f' in cases like this when 'f' is to be of a pointer
    to function type. Can you shed some light on your views?
    Tim Rentsch, Jun 17, 2010
    #5
  6. aleksa

    Tim Rentsch Guest

    John Bode <> writes:

    > On May 10, 7:53 am, "BGB / cr88192" <> wrote:
    >> "Richard Heathfield" <> wrote in message
    >>
    >> news:...
    >>
    >>
    >>
    >>
    >>
    >> > aleksa wrote:
    >> >> typedef void (*PROC) (void); // v1
    >> >> typedef void (PROC) (void); // v2

    >>
    >> >> void foo (PROC callme)
    >> >> {
    >> >> callme();
    >> >> }

    >>
    >> >> Do I use V1 or V2 when defining PROC?

    >>
    >> > I'd do it this way:

    >>
    >> > typedef void PROC(void);

    >>
    >> > void foo(PROC *callme)
    >> > {
    >> > (*callme)();
    >> > }

    >>
    >> > This way avoids hiding the pointeriness of callme behind a typedef.

    >>
    >> but, this form looks more ugly...
    >>
    >> there is no reason to make things more ugly than they need to be...
    >>
    >> we could just as easily imagine that this were some-other-language, where
    >> functions typically are first-class, and most objects are reference-types
    >> without explicit pointer marks...
    >>
    >> then, there is no confusion about the function pointer, they just take
    >> something and call it...- Hide quoted text -
    >>
    >> - Show quoted text -

    >
    > Bitter experience has taught me that hiding a pointer behind a typedef
    > inevitably leads to heartburn.


    What experience(s) have you had in this regard with pointer-to-
    function types for function parameters?

    > Eventually someone forgets they're
    > dealing with a pointer type and tries to use '&' when they don't need
    > to, or attempts to use '.' when they meant '->', or forgets that they
    > need to use '*' before passing it to another function, etc.


    Won't all of these be caught by the compiler for pointer-to
    function arguments? (I admit I'm assuming the presence of
    function prototypes, but these days anyone who doesn't use
    function prototypes essentially always seems to be just
    asking for trouble anyway.)

    > Unless
    > it's something you will never have to dereference (either explicitly
    > with * or implicitly with -> or []), then IME it's best to explicitly
    > declare the object as a pointer.


    You mean, like not having to derefence a pointer-to-function,
    because it's dereferenced automatically whenever it's used
    to call a function? It seems to me that there is _never_
    any need to use some sort of dereferencing operator in
    conjunction with a pointer-to-function. Of course, some
    people may prefer to write '(*foo)()' rather than just 'foo()',
    but that seems more like choice than necessity. Is that
    different from your experience/view on the subject?
    Tim Rentsch, Jun 17, 2010
    #6
  7. Tim Rentsch <> writes:

    > Ben Bacarisse <> writes:

    <snip>
    >> typedef void Proc(void);
    >>
    >> However, I'd then write:
    >>
    >> void foo (Proc *callme)
    >> {
    >> callme();
    >> }
    >>
    >> so that the fact that a pointer is being passed is obvious. Function
    >> types in parameter lists are converted to pointer-to-function types but
    >> it's clearer, in my view, if you make the pointer explicit.

    >
    > I understand you're expressing what is in essence just a personal
    > opinion. Still I would like to ask for some amount of explanation
    > or elaboration. Personally I don't see any value to using 'Foo *f'
    > instead of 'Foo f' in cases like this when 'f' is to be of a pointer
    > to function type. Can you shed some light on your views?


    Not really! It's largely habit formed from history. The C I learnt
    (K&R C) did not have the automatic conversion of a parameter from
    function type to pointer to function type (though it did have that
    conversion for array types). Also, a function was called by writing a
    function-valued expression before the ()s not a pointer-to-function
    expression as now. Hence one had to write:

    void foo()
    Proc *callme;
    {
    (*callme)();
    }

    Whilst I appreciate the simplification of having a pointer-to-function
    expression for calling, I've not internalised the conversion in the
    parameter list, so I prefer to see it for what it is rather than rely on
    the conversion.

    You say you don't see any value in using Foo *f. Fair enough. Do you
    see any value in preferring Foo f? I had a narrow preference for the
    explicit nature of Foo *f and I can't see any reason to drop the * (I am
    certain neither of us values fewer keystrokes for the sake of it).

    --
    Ben.
    Ben Bacarisse, Jun 17, 2010
    #7
  8. Tim Rentsch <> writes:

    > John Bode <> writes:

    <snip>
    >> Unless
    >> it's something you will never have to dereference (either explicitly
    >> with * or implicitly with -> or []), then IME it's best to explicitly
    >> declare the object as a pointer.


    A function pointer is one such beast. You never have to dereference it,
    either implicitly of explicitly.

    > You mean, like not having to derefence a pointer-to-function,
    > because it's dereferenced automatically whenever it's used
    > to call a function?


    It isn't -- not anymore.

    > It seems to me that there is _never_
    > any need to use some sort of dereferencing operator in
    > conjunction with a pointer-to-function. Of course, some
    > people may prefer to write '(*foo)()' rather than just 'foo()',
    > but that seems more like choice than necessity. Is that
    > different from your experience/view on the subject?


    Since all functions are now (post 1990) called through a pointer, adding
    the * to the call is obfuscation. The pointer gets converted to a
    function value which "decays" back to a pointer for the call.

    --
    Ben.
    Ben Bacarisse, Jun 17, 2010
    #8
  9. On 10 May, 15:21, John Bode <> wrote:
    > On May 10, 7:53 am, "BGB / cr88192" <> wrote:
    > > "Richard Heathfield" <> wrote in message
    > >news:...
    > > > aleksa wrote:



    > > >> typedef void (*PROC) (void); // v1
    > > >> typedef void  (PROC) (void); // v2

    >
    > > >> void foo (PROC callme)
    > > >> {
    > > >>     callme();
    > > >> }

    >
    > > >> Do I use V1 or V2 when defining PROC?

    >
    > > > I'd do it this way:

    >
    > > > typedef void PROC(void);

    >
    > > > void foo(PROC *callme)
    > > > {
    > > >   (*callme)();
    > > > }

    >
    > > > This way avoids hiding the pointeriness of callme behind a typedef.

    >
    > > but, this form looks more ugly...


    ugliness is int he eye of the beholder. I;m almost sold on Richard's
    way of doing it. THough I don't like all upper case typedefs. And I
    think function pointers are sufficiently unusual to resort to mild
    Hungarian (<spit>)

    fixing the poor layout as well, we have...

    typedef void Callback_function (void);

    void foo (Callback_function* callme)
    {
    callme ();
    }


    > > there is no reason to make things more ugly than they need to be...


    I don't bother with the fancy call syntax


    > > we could just as easily imagine that this were some-other-language, where
    > > functions typically are first-class, and most objects are reference-types
    > > without explicit pointer marks...


    yes we could but we aren't programming in that language we are
    programming in C

    (define foo (lambda (callme) (callme)))


    > > then, there is no confusion about the function pointer, they just take
    > > something and call it...


    so what... Could you give an example that illustrates your point. You
    can't really call someone's code "ugly" if you won't produce your own,
    beautiful, code.

    > Bitter experience has taught me that hiding a pointer behind a typedef
    > inevitably leads to heartburn[1].



    I'd make an exception for function pointers (though I do go a bit
    hungarian)

    > Eventually someone forgets they're
    > dealing with a pointer type and tries to use '&' when they don't need
    > to, or attempts to use '.' when they meant '->',


    not with a fucntion pointer they don't

    > or forgets that they
    > need to use '*' before passing it to another function, etc.  Unless
    > it's something you will never have to dereference (either explicitly
    > with * or implicitly with -> or []), then IME it's best to explicitly
    > declare the object as a pointer.


    yes, but none of this applies to FPs

    > 1.  In C, anyway; I am slowly learning that C++ is a very different
    > animal in this regard, especially when it comes to writing templates,
    > although I've seen this same problem bite other people in the ass in C+
    > +.


    templates are the work of the devil


    --

    A good designer must rely on experience, on precise, logic thinking;
    and on pedantic exactness. No magic will do.
    (Wirth)
    Nick Keighley, Jun 18, 2010
    #9
  10. aleksa

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > Tim Rentsch <> writes:
    >
    >> Ben Bacarisse <> writes:

    > <snip>
    >>> typedef void Proc(void);
    >>>
    >>> However, I'd then write:
    >>>
    >>> void foo (Proc *callme)
    >>> {
    >>> callme();
    >>> }
    >>>
    >>> so that the fact that a pointer is being passed is obvious. Function
    >>> types in parameter lists are converted to pointer-to-function types but
    >>> it's clearer, in my view, if you make the pointer explicit.

    >>
    >> I understand you're expressing what is in essence just a personal
    >> opinion. Still I would like to ask for some amount of explanation
    >> or elaboration. Personally I don't see any value to using 'Foo *f'
    >> instead of 'Foo f' in cases like this when 'f' is to be of a pointer
    >> to function type. Can you shed some light on your views?

    >
    > Not really! It's largely habit formed from history. The C I learnt
    > (K&R C) did not have the automatic conversion of a parameter from
    > function type to pointer to function type (though it did have that
    > conversion for array types). Also, a function was called by writing a
    > function-valued expression before the ()s not a pointer-to-function
    > expression as now. Hence one had to write:
    >
    > void foo()
    > Proc *callme;
    > {
    > (*callme)();
    > }
    >
    > Whilst I appreciate the simplification of having a pointer-to-function
    > expression for calling, I've not internalised the conversion in the
    > parameter list, so I prefer to see it for what it is rather than rely on
    > the conversion.
    >
    > You say you don't see any value in using Foo *f. Fair enough. Do you
    > see any value in preferring Foo f? I had a narrow preference for the
    > explicit nature of Foo *f and I can't see any reason to drop the * (I am
    > certain neither of us values fewer keystrokes for the sake of it).


    Like you, I originally learned C from K&R, with the (*f)() syntax
    for calling through function pointers. I like the new syntax
    rule, mostly because calls look cleaner.

    I prefer using the 'Foo f' declaration, rather than 'Foo *f', for
    several different reasons. Here are some (I'm not claiming
    the list is exhaustive just yet):

    1. ISO C has eliminated most of the difference between a function
    type and a pointer to function type. I think removing this
    distinction (which is somewhat artificial) is an improvement in
    C, and using 'Foo f' is some movement in that direction.

    2. Following the C rule that "declaration mimics use", using 'Foo *f'
    seems wrong, because I certainly don't write '*f()', but '(*f)()'
    looks like it doesn't match the declaration either.

    3. If I need to have a parameter that is a pointer to a pointer
    to a function, it seems better to use only one '*' in the
    declaration, because those cases will really /need/ the '*';
    for example, '*fp = call_back', or '(*fp)()'. Because I write
    calls through plain pointer-to-function as 'f()', normally
    I would write calls through pointer-to-pointer-to-function
    as '(*fp)()', not '(**fp)()'.

    4. If given a choice, I would like to indicate somehow that some
    variable is a (pointer to) a function, but usually I would do this
    using the type name, eg, 'XYZ_callback_f blah', with the '_f'
    meaning function (or pointer to function).

    Summarizing: I don't find that the '*' adds anything, except
    it does add some confusion; conversely, leaving out the '*'
    seems to fit better with the new rules for how functions
    and pointers-to-function behave, and I've embraced that
    direction.

    So for what it's worth, those are my thoughts on the matter.
    Tim Rentsch, Jun 20, 2010
    #10
  11. Tim Rentsch <> writes:

    > Ben Bacarisse <> writes:
    >
    >> Tim Rentsch <> writes:
    >>
    >>> Ben Bacarisse <> writes:

    >> <snip>
    >>>> typedef void Proc(void);
    >>>>
    >>>> However, I'd then write:
    >>>>
    >>>> void foo (Proc *callme)
    >>>> {
    >>>> callme();
    >>>> }
    >>>>
    >>>> so that the fact that a pointer is being passed is obvious. Function
    >>>> types in parameter lists are converted to pointer-to-function types but
    >>>> it's clearer, in my view, if you make the pointer explicit.
    >>>
    >>> I understand you're expressing what is in essence just a personal
    >>> opinion. Still I would like to ask for some amount of explanation
    >>> or elaboration. Personally I don't see any value to using 'Foo *f'
    >>> instead of 'Foo f' in cases like this when 'f' is to be of a pointer
    >>> to function type. Can you shed some light on your views?

    >>
    >> Not really! It's largely habit formed from history. The C I learnt
    >> (K&R C) did not have the automatic conversion of a parameter from
    >> function type to pointer to function type (though it did have that
    >> conversion for array types). Also, a function was called by writing a
    >> function-valued expression before the ()s not a pointer-to-function
    >> expression as now. Hence one had to write:
    >>
    >> void foo()
    >> Proc *callme;
    >> {
    >> (*callme)();
    >> }
    >>
    >> Whilst I appreciate the simplification of having a pointer-to-function
    >> expression for calling, I've not internalised the conversion in the
    >> parameter list, so I prefer to see it for what it is rather than rely on
    >> the conversion.
    >>
    >> You say you don't see any value in using Foo *f. Fair enough. Do you
    >> see any value in preferring Foo f? I had a narrow preference for the
    >> explicit nature of Foo *f and I can't see any reason to drop the * (I am
    >> certain neither of us values fewer keystrokes for the sake of it).

    >
    > Like you, I originally learned C from K&R, with the (*f)() syntax
    > for calling through function pointers. I like the new syntax
    > rule, mostly because calls look cleaner.
    >
    > I prefer using the 'Foo f' declaration, rather than 'Foo *f', for
    > several different reasons. Here are some (I'm not claiming
    > the list is exhaustive just yet):
    >
    > 1. ISO C has eliminated most of the difference between a function
    > type and a pointer to function type. I think removing this
    > distinction (which is somewhat artificial) is an improvement in
    > C, and using 'Foo f' is some movement in that direction.


    I agree with this one but not quite enough to break the habit (yet)!

    > 2. Following the C rule that "declaration mimics use", using 'Foo *f'
    > seems wrong, because I certainly don't write '*f()', but '(*f)()'
    > looks like it doesn't match the declaration either.


    This is not, for me, a strong argument. I don't think there is a "rule"
    that declaration follows use but if there is it is often broken: the
    operators ., ->, [] and () all mess it up to some extent. A C
    programmer simply has to know what there operators do and the fact that
    one of them -- function call -- can be tidied up by sticking to a
    particular convention in the declaration of function parameters is not
    much of a gain.

    One could argue that there is at least as much asymmetry in the fact
    that

    Func f;

    and

    void doit(Func f);

    exhibit quite different meanings for apparently similar declarations.
    I.e. while your usage reduces surprise in one quarter, it can introduce
    it in another because if you want an object with the same type as the
    parameter, the * is required.

    > 3. If I need to have a parameter that is a pointer to a pointer
    > to a function, it seems better to use only one '*' in the
    > declaration, because those cases will really /need/ the '*';
    > for example, '*fp = call_back', or '(*fp)()'. Because I write
    > calls through plain pointer-to-function as 'f()', normally
    > I would write calls through pointer-to-pointer-to-function
    > as '(*fp)()', not '(**fp)()'.


    Unless I've misunderstood you we must be talking about different things
    here. The context was that we have a function type (Func, say) and we
    are discussing the merits of

    void doit(Func f);

    vs.

    void doit(Func *f);

    In this context, I don't see how you can have just one * when the
    parameter is a pointer to a function pointer. Maybe you are thinking
    about a related matter: hiding the pointer in the function typedef?

    If anything, your point 3 is a case for my usage. The distinction
    between Func *f and Func **f is clear and unsurprising, but having to
    switch from Func f to Func **f when adding just one level of indirection
    is surely a source of potential confusion?

    > 4. If given a choice, I would like to indicate somehow that some
    > variable is a (pointer to) a function, but usually I would do this
    > using the type name, eg, 'XYZ_callback_f blah', with the '_f'
    > meaning function (or pointer to function).


    I don't see how this relates to the declaration. Are you saying that
    having both an indicative name and a * in the declaration is overkill?
    I am quite happy to have both.

    > Summarizing: I don't find that the '*' adds anything, except
    > it does add some confusion; conversely, leaving out the '*'
    > seems to fit better with the new rules for how functions
    > and pointers-to-function behave, and I've embraced that
    > direction.


    I can see your point, but I don't find that the * adds much significant
    confusion. There are cases where leaving it out can also be seen as
    confusing though I grant that they are rare enough that they can
    probably be discounted.

    > So for what it's worth, those are my thoughts on the matter.


    Likewise. I was away for a week and I fear that this minor topic might
    be being extended beyond its significance but your considered response
    deserved some reply.

    --
    Ben.
    Ben Bacarisse, Jun 27, 2010
    #11
  12. aleksa

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > Tim Rentsch <> writes:
    >
    >> Ben Bacarisse <> writes:
    >>
    >>> Tim Rentsch <> writes:
    >>>
    >>>> Ben Bacarisse <> writes:
    >>> <snip>
    >>>>> typedef void Proc(void);
    >>>>>
    >>>>> However, I'd then write:
    >>>>>
    >>>>> void foo (Proc *callme)
    >>>>> {
    >>>>> callme();
    >>>>> }
    >>>>>
    >>>>> so that the fact that a pointer is being passed is obvious. Function
    >>>>> types in parameter lists are converted to pointer-to-function types but
    >>>>> it's clearer, in my view, if you make the pointer explicit.
    >>>>
    >>>> I understand you're expressing what is in essence just a personal
    >>>> opinion. Still I would like to ask for some amount of explanation
    >>>> or elaboration. Personally I don't see any value to using 'Foo *f'
    >>>> instead of 'Foo f' in cases like this when 'f' is to be of a pointer
    >>>> to function type. Can you shed some light on your views?
    >>>
    >>> Not really! It's largely habit formed from history. The C I learnt
    >>> (K&R C) did not have the automatic conversion of a parameter from
    >>> function type to pointer to function type (though it did have that
    >>> conversion for array types). Also, a function was called by writing a
    >>> function-valued expression before the ()s not a pointer-to-function
    >>> expression as now. Hence one had to write:
    >>>
    >>> void foo()
    >>> Proc *callme;
    >>> {
    >>> (*callme)();
    >>> }
    >>>
    >>> Whilst I appreciate the simplification of having a pointer-to-function
    >>> expression for calling, I've not internalised the conversion in the
    >>> parameter list, so I prefer to see it for what it is rather than rely on
    >>> the conversion.
    >>>
    >>> You say you don't see any value in using Foo *f. Fair enough. Do you
    >>> see any value in preferring Foo f? I had a narrow preference for the
    >>> explicit nature of Foo *f and I can't see any reason to drop the * (I am
    >>> certain neither of us values fewer keystrokes for the sake of it).

    >>
    >> Like you, I originally learned C from K&R, with the (*f)() syntax
    >> for calling through function pointers. I like the new syntax
    >> rule, mostly because calls look cleaner.
    >>
    >> I prefer using the 'Foo f' declaration, rather than 'Foo *f', for
    >> several different reasons. Here are some (I'm not claiming
    >> the list is exhaustive just yet):
    >>
    >> 1. ISO C has eliminated most of the difference between a function
    >> type and a pointer to function type. I think removing this
    >> distinction (which is somewhat artificial) is an improvement in
    >> C, and using 'Foo f' is some movement in that direction.

    >
    > I agree with this one but not quite enough to break the habit (yet)!
    >
    >> 2. Following the C rule that "declaration mimics use", using 'Foo *f'
    >> seems wrong, because I certainly don't write '*f()', but '(*f)()'
    >> looks like it doesn't match the declaration either.

    >
    > This is not, for me, a strong argument. [snip elaboration]


    Oh, I wasn't meaning to make an argument, just explain my
    own thoughts on the matter. I wasn't trying (or expecting)
    to convince anyone.

    > One could argue that there is at least as much asymmetry in the fact
    > that
    >
    > Func f;
    >
    > and
    >
    > void doit(Func f);
    >
    > exhibit quite different meanings for apparently similar declarations.
    > I.e. while your usage reduces surprise in one quarter, it can introduce
    > it in another because if you want an object with the same type as the
    > parameter, the * is required.


    Oops, there is a bit of confusion here that I should clear
    up. My intention is that the type 'Func' include the pointerness
    of pointer-to-function (eg, 'typedef void (*Func)(int)').
    I rarely define actual function types, since they are almost
    never the types the program needs.


    >> 3. If I need to have a parameter that is a pointer to a pointer
    >> to a function, it seems better to use only one '*' in the
    >> declaration, because those cases will really /need/ the '*';
    >> for example, '*fp = call_back', or '(*fp)()'. Because I write
    >> calls through plain pointer-to-function as 'f()', normally
    >> I would write calls through pointer-to-pointer-to-function
    >> as '(*fp)()', not '(**fp)()'.

    >
    > Unless I've misunderstood you we must be talking about different things
    > here. The context was that we have a function type (Func, say) and we
    > are discussing the merits of
    >
    > void doit(Func f);
    >
    > vs.
    >
    > void doit(Func *f);
    >
    > In this context, I don't see how you can have just one * when the
    > parameter is a pointer to a function pointer. Maybe you are thinking
    > about a related matter: hiding the pointer in the function typedef?


    As above, I do mean putting the pointerness in the function typedef,
    although I don't think of it as "hiding".

    > If anything, your point 3 is a case for my usage. The distinction
    > between Func *f and Func **f is clear and unsurprising, but having to
    > switch from Func f to Func **f when adding just one level of indirection
    > is surely a source of potential confusion?


    Yes, and I might list that as a reason for putting the
    function-pointerness in the typedef for 'Func'. Normally
    I think it's a good idea to avoid actual function types
    for function parameters -- too many chances for some
    confusion between pre-adjusted and post-adjusted types.


    >> 4. If given a choice, I would like to indicate somehow that some
    >> variable is a (pointer to) a function, but usually I would do this
    >> using the type name, eg, 'XYZ_callback_f blah', with the '_f'
    >> meaning function (or pointer to function).

    >
    > I don't see how this relates to the declaration. Are you saying that
    > having both an indicative name and a * in the declaration is overkill?
    > I am quite happy to have both.


    I am meaning to make an orthogonal statement. Or, to say that
    another way, I don't want to have to depend on the '*' to
    indicate a function parameter. So function type names (usually
    pointer-to-function, but actual function types also) normally
    should have some sort of indicator in the type name to show
    the functionness.


    >> Summarizing: I don't find that the '*' adds anything, except
    >> it does add some confusion; conversely, leaving out the '*'
    >> seems to fit better with the new rules for how functions
    >> and pointers-to-function behave, and I've embraced that
    >> direction.

    >
    > I can see your point, but I don't find that the * adds much significant
    > confusion.


    Yes, "confusion" is probably not quite the right term;
    "cognitive load", perhaps. Whatever the word I agree
    the magnitude is small, although for me it is definitely
    non-zero.

    > There are cases where leaving it out can also be seen as
    > confusing though I grant that they are rare enough that they can
    > probably be discounted.


    Right. It would be nice to do an actual, controlled experiment
    to try to measure these things, rather than having to rely on
    personal or anecdotal experience. My sense is that changes
    like this are often sea changes, and it's hard to see results
    in isolation. However I don't have any sort of hard data to
    back that up.


    >> So for what it's worth, those are my thoughts on the matter.

    >
    > Likewise. I was away for a week and I fear that this minor topic might
    > be being extended beyond its significance but your considered response
    > deserved some reply.


    No worries. I appreciate the return comments.
    Tim Rentsch, Jun 28, 2010
    #12
  13. Tim Rentsch <> writes:
    > Ben Bacarisse <> writes:

    <snip>
    >> One could argue that there is at least as much asymmetry in the fact
    >> that
    >>
    >> Func f;
    >>
    >> and
    >>
    >> void doit(Func f);
    >>
    >> exhibit quite different meanings for apparently similar declarations.
    >> I.e. while your usage reduces surprise in one quarter, it can introduce
    >> it in another because if you want an object with the same type as the
    >> parameter, the * is required.

    >
    > Oops, there is a bit of confusion here that I should clear
    > up. My intention is that the type 'Func' include the pointerness
    > of pointer-to-function (eg, 'typedef void (*Func)(int)').


    Ah. We've been talking about different things. Note you did comment
    directly on my example that did not include the pointerness in the
    typedef!

    When the defined type includes the pointerness then there is only one
    correct usage (Func f) but I'd probably include a hint in the type name
    (void (*Funcp)(int)). When the type is a function type (void Func(int))
    avoiding the automatic parameter type adjustment seems to me clearer --
    hence my preference for a * in a parameter declaration in such cases but
    that is not, it seems, what you were talking about.

    My preference for not including the * in the typedef is partly explained
    here:

    > I rarely define actual function types, since they are almost
    > never the types the program needs.


    In several cases I've found them useful which may explain our different
    preferences. In more than once case I've found the ability to declare
    external functions via a function type to be handy:

    typedef Value Operator(Value *);
    extern Operator op_add, op_sub, op_mul, op_div /* ... */;
    Operator *op_table[] = {
    op_add, op_sub, op_mul, op_div /* ... */
    };

    The advantage grows if you are using the pre-processor:

    extern Operator OP_LIST;
    Operator *op_table[] = { OP_LIST };

    <snip>
    --
    Ben.
    Ben Bacarisse, Jun 28, 2010
    #13
  14. aleksa

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > Tim Rentsch <> writes:
    >> Ben Bacarisse <> writes:

    > <snip>
    >>> One could argue that there is at least as much asymmetry in the fact
    >>> that
    >>>
    >>> Func f;
    >>>
    >>> and
    >>>
    >>> void doit(Func f);
    >>>
    >>> exhibit quite different meanings for apparently similar declarations.
    >>> I.e. while your usage reduces surprise in one quarter, it can introduce
    >>> it in another because if you want an object with the same type as the
    >>> parameter, the * is required.

    >>
    >> Oops, there is a bit of confusion here that I should clear
    >> up. My intention is that the type 'Func' include the pointerness
    >> of pointer-to-function (eg, 'typedef void (*Func)(int)').

    >
    > Ah. We've been talking about different things. Note you did comment
    > directly on my example that did not include the pointerness in the
    > typedef!


    Yes, it's possible I missed or glossed over this difference,
    expecting my comments would be understood from context.
    Sorry about that.

    > When the defined type includes the pointerness then there is only one
    > correct usage (Func f) but I'd probably include a hint in the type name
    > (void (*Funcp)(int)).


    Right, and reasoning backwards I thought you would realize
    that I intended the * to be in the typedef. Silly me. :)

    > When the type is a function type (void Func(int))
    > avoiding the automatic parameter type adjustment seems to me clearer --
    > hence my preference for a * in a parameter declaration in such cases but
    > that is not, it seems, what you were talking about.


    I'm generally in agreement on this, and that's another reason
    why I thought you'd understand I intended the * to be in the
    typedef. Silly me. :)


    > My preference for not including the * in the typedef is partly explained
    > here:
    >
    >> I rarely define actual function types, since they are almost
    >> never the types the program needs.

    >
    > In several cases I've found them useful which may explain our different
    > preferences. In more than once case I've found the ability to declare
    > external functions via a function type to be handy:
    >
    > typedef Value Operator(Value *);
    > extern Operator op_add, op_sub, op_mul, op_div /* ... */;
    > Operator *op_table[] = {
    > op_add, op_sub, op_mul, op_div /* ... */
    > };
    >
    > The advantage grows if you are using the pre-processor:
    >
    > extern Operator OP_LIST;
    > Operator *op_table[] = { OP_LIST };


    Yes, I understand the motivation provided by this example. It's
    not as compelling for me because I almost never write function
    declarations by hand; in almost all cases they are generated
    automatically from the definitions and mechanically made
    available in the appropriate header files. Because of that
    normally I would just #include the appropriate header files, and
    not write the 'extern Operator ...' lines. Hence there wouldn't
    be any need for the non-pointer function type, and there would
    be a typedef just for the pointer-ful function type.
    Tim Rentsch, Jun 28, 2010
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve Green

    java needs typedef

    Steve Green, Mar 24, 2005, in forum: Java
    Replies:
    11
    Views:
    11,373
    Joona I Palaste
    Mar 25, 2005
  2. qazmlp

    typedef enum

    qazmlp, Jul 2, 2003, in forum: C++
    Replies:
    2
    Views:
    457
    Alexander Terekhov
    Jul 2, 2003
  3. Mike P
    Replies:
    0
    Views:
    3,295
    Mike P
    Jun 19, 2006
  4. oor
    Replies:
    0
    Views:
    1,343
  5. AlexWare
    Replies:
    2
    Views:
    752
    Paul Uiterlinden
    Oct 23, 2009
Loading...

Share This Page