The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> C Programming
|
function pointer stuff
Discuss function pointer stuff in the C Programming forum on Dev Shed. function pointer stuff C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

April 8th, 2003, 12:10 PM
|
|
.
|
|
Join Date: Dec 2002
Posts: 296
Time spent in forums: < 1 sec
Reputation Power: 11
|
|
|
function pointer stuff
this function call line is confusing me a bit:
Code:
qsorty((void **) lineptr, 0, nlines-1, (int (*)(void *, void *))(fold ? strcmpulc : strcmp));
i don't understand what the (void **) part is. it doesn't match up with the qsorty decleration which is:
Code:
void qsorty(void *lineptr[], int left, int right, int (*comp)(void *, void *));
also the (int (*)(void *, void *))(fold ? strcmpulc : strcmp) part from the function call i kind of understand. it seems that it's working a bit like the %d's in a printf statement - the place holder is getting replaced. so (*) is getting replaced by the answer to fold ? which is going to be one of the two pointers to functions.
what is that makes it behave like that? is that something to do with the (void **) maybe? (i'm guessing)
also, say you've got a situation where there isn't any option about which function pointer should be passed (like in the (fold ? strcmpulc : strcmp) part), is this the only way to say that? :
Code:
qsorty((void **) lineptr, 0, nlines-1, (int (*)(void *, void *))(numcmp));
that works but it seems like it should be possible to use something like:
Code:
qsorty((void **) lineptr, 0, nlines-1, (int (*numcmp)(void *, void *)));
or
Code:
qsorty((void **) lineptr, 0, nlines-1, (*numcmp)(void *, void *));
but they aren't ok.
|

April 8th, 2003, 01:23 PM
|
 |
*bounce*
|
|
Join Date: Jan 2002
Location: Delft, The Netherlands
|
|
Quote: | i don't understand what the (void **) part is. it doesn't match up with the qsorty declaration... |
Bear in mind that in a function declaration (and only in a function declaration!) pointer-to-type and array-of-type are identical; they're synonymous, and the only reason why you might want to choose array-of-type (type[]) over pointer-to-type (type*) is as a hint to the programmer that it doesn't point to a single element of type, but to the first in a sequence of type.
In the function call I assume that lineptr is an array of pointer-to-char, which is why the typecast to (void **) makes sense, being that in a function declaration, **void is identical to *void[] as I just explained.
Quote: | also the (int (*)(void *, void *))(fold ? strcmpulc : strcmp) part from the function call i kind of understand. it seems that it's working a bit like the %d's in a printf statement - the place holder is getting replaced. so (*) is getting replaced by the answer to fold ? which is going to be one of the two pointers to functions. |
Let's break that up into two pieces, the first part being a typecast, and the second being the conditional operator:
The (fold ? strcmpulc : strcmp) bit is fairly straight-forward; it's the conditional operator ?: (check A7.16 on page 208 of K&R if you're unfamiliar with it).
Basically that expression evaluates to either strcmpulc or strcmp, depending on the value of fold. So what you get, is a function pointer.
The problem is that qsorty expects a pointer to a function that has a prototype of
Code:
int (*cmp)(void *, void *)
, but strcmp and strcmpulc are (probably) declared as
Code:
int (*cmp)(const char *, const char *)
That's what the typecast is for. It might look draconian, but yes, it really is a typecast.  It casts the pointer-to-function-with-two-pointer-to- char-arguments-and-returning-an-int
to a pointer-to-function-with-two-pointer-to- void-arguments-and-returning-an-int.
Code:
int (*)(void *, void *)
can be broken down as follows:
Code:
int /* returning an int */
(*) /* pointer-to */
(void *, void *) /* function with two pointer-to-void arguments */
It needs the parentheses around the asterisk (the pointer-to bit) to make sure it isn't associated with the return type, int.
I hope this clears things up a bit. Keep asking though; it keeps us on our toes 
__________________
"A poor programmer is he who blames his tools."
http://analyser.oli.tudelft.nl/
|

April 9th, 2003, 08:50 AM
|
|
.
|
|
Join Date: Dec 2002
Posts: 296
Time spent in forums: < 1 sec
Reputation Power: 11
|
|
thanks for your reply.
Quote: , but strcmp and strcmpulc are (probably) declared as
Code:
int (*cmp)(const char *, const char *)
|
they're just declared normally :
Code:
int strcmpulc(char *, char *);
and the other is part of string.h so it's also declared in the usual way. maybe that's why i get :
warning: pointer type mismatch in conditional expression
for that line?  probably is. but then saying that, on this function call line:
Code:
qsorty((void **) lineptr, 0, nlines-1, (int (*)(void *, void *))(numcmp));
i don't get that warning and numcmp is declared like so:
Code:
int numcmp(char *, char *);
Quote: (int (*)(void *, void *))(fold ? strcmpulc : strcmp)
two pieces, the first part being a typecast, and the second being the conditional operator |
i understand that apart from why, when there's no conditional aspect - only one possible function to call, can i not say:
Code:
(int (*strcmp)(void *, void *))
or something similar? does it have to be in two pieces even when no conitional element? (in the call to the function that is)
Quote: | I hope this clears things up a bit. |
a bit, yes thanks  i need to go over it a bit more to let it sink in
Last edited by balance : April 9th, 2003 at 08:57 AM.
|

April 9th, 2003, 02:29 PM
|
 |
*bounce*
|
|
Join Date: Jan 2002
Location: Delft, The Netherlands
|
|
Quote: | they're just declared normally |
Well, my emphasis wasn't on the consts, but the fact that it's char* instead of void*.
Quote: I understand that apart from why, when there's no conditional aspect - only one possible function to call, can i not say:
Code:
(int (*strcmp)(void *, void *))
or something similar? does it have to be in two pieces even when no conitional element? |
The code snippet above is just a semi-colon short of a declaration statement. It would declare strcmp as being a pointer-to-function. What the qsorty function call contains though, is a type cast, which has a general form of
Code:
(type-to-cast-to) (expression-to-cast)
Just like you can cast a real expression to an integer expression by saying (int)(3.14159), you can cast pointer-to-function expressions.
The thing is that not all function pointers are alike; some pointers point to a function that takes an int as an argument, others point to a function that returns a double, etc, etc. They're all different, because the functions' declarations are different.
Hence, when you've defined a function (qsorty in this case) that expects as its third parameter a pointer to a function that takes two pointer-to- void arguments, and you call it with its third argument being a pointer to a function that takes two pointer-to- char arguments (strcmp, for example), then you'll get a warning (if not error) saying that the types don't match. That's why you have to perform a type cast.
Quote: | i don't get that warning and numcmp is declared like so |
Again, that would be due to the type cast 
|

April 11th, 2003, 10:31 AM
|
|
.
|
|
Join Date: Dec 2002
Posts: 296
Time spent in forums: < 1 sec
Reputation Power: 11
|
|
ok i think i've got it. thanks-a-lot for your explenation analyser 
|

April 11th, 2003, 10:37 AM
|
 |
*bounce*
|
|
Join Date: Jan 2002
Location: Delft, The Netherlands
|
|
You're quite welcome 
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|