late-binding of name to function pointer and other questions

Discussion in 'C Programming' started by Dennis Chang, May 14, 2004.

  1. Dennis Chang

    Dennis Chang Guest

    Hi all,

    I was reading about function pointers and came across something which
    intrigued me.
    K&R2 calls qsort (pg.119) within main as so:

    qsort( (void **) lineptr, 0, nlines-1, (int (*) (void *, void*))(numeric ?
    numcmp : strcmp) );

    I guess what interests me is the nameless function pointer and then the
    binding of a name to it.

    I've worked with nameless functions before in other languages but not in C.

    So is my reading of this qsort function call correct?

    Another question presents itself to me on the following page of K&R2
    (pg.120).

    /* Declaration qsort */
    void qsort( ... )
    {
    void swap (void *, int, int);
    /* ... */
    }

    It's true you can't declare a function within a function? So that the
    forward declaration of swap within qsort doesn't prevent swap from being
    called from other functions (since it's defined elsewhere)? So what's the
    point of a forward declaration within a function declaration?

    Lastly, it is possible to declare a nameless function within a function?
    I.e.,
    int max20(int a)
    {
    return { a > 20 ? a : 20 };
    }

    I mean the {} declares a nameless function, no?


    Thanks,
    Dennis.
     
    Dennis Chang, May 14, 2004
    #1
    1. Advertising

  2. Dennis Chang

    Artie Gold Guest

    Dennis Chang wrote:
    > Hi all,
    >
    > I was reading about function pointers and came across something which
    > intrigued me.
    > K&R2 calls qsort (pg.119) within main as so:
    >
    > qsort( (void **) lineptr, 0, nlines-1, (int (*) (void *, void*))(numeric ?
    > numcmp : strcmp) );
    >
    > I guess what interests me is the nameless function pointer and then the
    > binding of a name to it.


    Nope. It's not a `nameless function pointer'. It's a cast.
    >
    > I've worked with nameless functions before in other languages but not in C.
    >
    > So is my reading of this qsort function call correct?


    See above.
    >
    > Another question presents itself to me on the following page of K&R2
    > (pg.120).
    >
    > /* Declaration qsort */
    > void qsort( ... )
    > {
    > void swap (void *, int, int);
    > /* ... */
    > }
    >
    > It's true you can't declare a function within a function? So that the


    Sure you can. But you can't *define* a function within a function.

    > forward declaration of swap within qsort doesn't prevent swap from being
    > called from other functions (since it's defined elsewhere)? So what's the
    > point of a forward declaration within a function declaration?
    >
    > Lastly, it is possible to declare a nameless function within a function?
    > I.e.,
    > int max20(int a)
    > {
    > return { a > 20 ? a : 20 };
    > }
    >
    > I mean the {} declares a nameless function, no?
    >

    No.
    In fact, the above is *not* standard C code.

    HTH,
    --ag

    --
    Artie Gold -- Austin, Texas
     
    Artie Gold, May 14, 2004
    #2
    1. Advertising

  3. Dennis Chang wrote:
    >
    > I was reading about function pointers and came across something which
    > intrigued me.
    > K&R2 calls qsort (pg.119) within main as so:
    >
    > qsort( (void **) lineptr, 0, nlines-1, (int (*) (void *, void*))(numeric ?
    > numcmp : strcmp) );


    N.B.: The qsort function in their example is not the same as the qsort
    function in the C standard library (see page 120 for the qsort function
    being used).

    > I guess what interests me is the nameless function pointer and then the
    > binding of a name to it.
    >
    > I've worked with nameless functions before in other languages but not in
    > C.
    >
    > So is my reading of this qsort function call correct?


    Are you talking about this part:

    (int (*) (void *, void*))(numeric ? numcmp : strcmp)

    ?

    I think you're confused about what's going on. First, this expression is
    evaluated:

    numeric ? numcmp : strcmp

    The result of the expression is the address of either numcmp or strcmp,
    depending on the value of numeric at run time.

    There's a problem here. The type of numcmp's address is:
    pointer-to-function-taking-two-char-pointers-and-returning-an-int. The type
    of strcmp's address is:
    pointer-to-function-taking-two-const-char-pointers-and-returning-an-int
    (notice the const). The two operands should be the same type, or at least
    the compiler should be able to convert one type to the other automatically.

    On page 208 of K&R, the authors write (about the second and third operands
    of conditional expressions), "In the type comparison for pointers, any type
    qualifiers [like const] in the type to which the pointer points are
    insignificant, but the result type inherits qualifiers from both arms of the
    conditional."

    So it should be okay, but one of the compilers I've tested this code on
    gives me an error, and another gives me a warning.

    Anyway, let's assume the result of the conditional expression is an address
    of type: pointer-to-function taking-two-char-pointers-and-returning-an-int.
    What qsort requires for its third parameter is a
    pointer-to-function-taking-two-void-pointers-and-returning-an-int. The
    conversion between those two types won't happen automatically. So this cast
    is added:

    (int (*) (void *, void *))

    This converts the address to the needed type.

    That cast strikes me as suspicious. I'm not sure it's portable.

    The authors themselves seem dissatisfied with their example. See their
    errata web page:

    http://www.cs.bell-labs.com/cm/cs/cbook/2ediffs.html

    > Another question presents itself to me on the following page of K&R2
    > (pg.120).
    >
    > /* Declaration qsort */
    > void qsort( ... )
    > {
    > void swap (void *, int, int);
    > /* ... */
    > }
    >
    > It's true you can't declare a function within a function?


    You can declare a function within a function (as above), but you can't
    define a function within a function.

    > So that the
    > forward declaration of swap within qsort doesn't prevent swap from being
    > called from other functions (since it's defined elsewhere)?


    Well, the declaration is in scope only within qsort. If you need the
    declaration to be visible outside qsort, you have to either type the
    declaration again, or move the declaration to some other scope.

    > So what's the point of a forward declaration within a function

    declaration?

    There's no law against it. I can't think of an advantage to doing it that
    way. Some people like the style, I guess.

    > Lastly, it is possible to declare a nameless function within a function?
    > I.e.,
    > int max20(int a)
    > {
    > return { a > 20 ? a : 20 };
    > }
    >
    > I mean the {} declares a nameless function, no?


    Well, no. That's a syntax error. There's no such thing as a nameless
    function in C.

    --
    Russell Hanneken

    Remove the 'g' from my address to send me mail.
     
    Russell Hanneken, May 14, 2004
    #3
  4. Dennis Chang

    Dennis Chang Guest

    "Russell Hanneken" <> wrote in message
    news:ts8pc.511$...
    > Dennis Chang wrote:
    > >
    > > I was reading about function pointers and came across something which
    > > intrigued me.
    > > K&R2 calls qsort (pg.119) within main as so:
    > >
    > > qsort( (void **) lineptr, 0, nlines-1, (int (*) (void *, void*))(numeric

    ?
    > > numcmp : strcmp) );

    >
    > N.B.: The qsort function in their example is not the same as the qsort
    > function in the C standard library (see page 120 for the qsort function
    > being used).
    >
    > > I guess what interests me is the nameless function pointer and then the
    > > binding of a name to it.
    > >
    > > I've worked with nameless functions before in other languages but not in
    > > C.
    > >
    > > So is my reading of this qsort function call correct?

    >
    > Are you talking about this part:
    >
    > (int (*) (void *, void*))(numeric ? numcmp : strcmp)
    >
    > ?
    >
    > I think you're confused about what's going on. First, this expression is
    > evaluated:
    >
    > numeric ? numcmp : strcmp
    >
    > The result of the expression is the address of either numcmp or strcmp,
    > depending on the value of numeric at run time.
    >
    > There's a problem here. The type of numcmp's address is:
    > pointer-to-function-taking-two-char-pointers-and-returning-an-int. The

    type
    > of strcmp's address is:
    > pointer-to-function-taking-two-const-char-pointers-and-returning-an-int
    > (notice the const). The two operands should be the same type, or at least
    > the compiler should be able to convert one type to the other

    automatically.
    >
    > On page 208 of K&R, the authors write (about the second and third operands
    > of conditional expressions), "In the type comparison for pointers, any

    type
    > qualifiers [like const] in the type to which the pointer points are
    > insignificant, but the result type inherits qualifiers from both arms of

    the
    > conditional."
    >
    > So it should be okay, but one of the compilers I've tested this code on
    > gives me an error, and another gives me a warning.
    >
    > Anyway, let's assume the result of the conditional expression is an

    address
    > of type: pointer-to-function

    taking-two-char-pointers-and-returning-an-int.
    > What qsort requires for its third parameter is a
    > pointer-to-function-taking-two-void-pointers-and-returning-an-int. The
    > conversion between those two types won't happen automatically. So this

    cast
    > is added:
    >
    > (int (*) (void *, void *))
    >
    > This converts the address to the needed type.
    >
    > That cast strikes me as suspicious. I'm not sure it's portable.
    >
    > The authors themselves seem dissatisfied with their example. See their
    > errata web page:
    >
    > http://www.cs.bell-labs.com/cm/cs/cbook/2ediffs.html
    >
    > > Another question presents itself to me on the following page of K&R2
    > > (pg.120).
    > >
    > > /* Declaration qsort */
    > > void qsort( ... )
    > > {
    > > void swap (void *, int, int);
    > > /* ... */
    > > }
    > >
    > > It's true you can't declare a function within a function?

    >
    > You can declare a function within a function (as above), but you can't
    > define a function within a function.
    >
    > > So that the
    > > forward declaration of swap within qsort doesn't prevent swap from being
    > > called from other functions (since it's defined elsewhere)?

    >
    > Well, the declaration is in scope only within qsort. If you need the
    > declaration to be visible outside qsort, you have to either type the
    > declaration again, or move the declaration to some other scope.
    >
    > > So what's the point of a forward declaration within a function

    > declaration?
    >
    > There's no law against it. I can't think of an advantage to doing it that
    > way. Some people like the style, I guess.
    >
    > > Lastly, it is possible to declare a nameless function within a function?
    > > I.e.,
    > > int max20(int a)
    > > {
    > > return { a > 20 ? a : 20 };
    > > }
    > >
    > > I mean the {} declares a nameless function, no?

    >
    > Well, no. That's a syntax error. There's no such thing as a nameless
    > function in C.
    >
    > --
    > Russell Hanneken
    >
    > Remove the 'g' from my address to send me mail.
    >
    >


    Thanks for both your responses. It's clear now. :O)
    Dennis.
     
    Dennis Chang, May 15, 2004
    #4
    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. ThunderMusic

    Plugins and Late Binding

    ThunderMusic, Jan 27, 2005, in forum: ASP .Net
    Replies:
    4
    Views:
    876
    Patrice
    Apr 12, 2005
  2. PatLaf

    problem with owc10 and late binding

    PatLaf, Jan 9, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    338
    Ken Cox [Microsoft MVP]
    Jan 10, 2004
  3. Olaf Meding

    MS COM early and late binding

    Olaf Meding, Apr 27, 2004, in forum: Python
    Replies:
    4
    Views:
    431
    Simon Brunning
    Apr 28, 2004
  4. Replies:
    2
    Views:
    912
    Kevin Grover
    Oct 20, 2006
  5. Replies:
    0
    Views:
    315
Loading...

Share This Page