By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,275 Members | 920 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,275 IT Pros & Developers. It's quick & easy.

late-binding of name to function pointer and other questions

P: n/a
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.
Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
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
Nov 14 '05 #2

P: n/a
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
rg********@pobox.com
Remove the 'g' from my address to send me mail.
Nov 14 '05 #3

P: n/a

"Russell Hanneken" <rg********@pobox.com> wrote in message
news:ts***************@newsread1.news.pas.earthlin k.net...
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
rg********@pobox.com
Remove the 'g' from my address to send me mail.


Thanks for both your responses. It's clear now. :O)
Dennis.
Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.