Click to See Complete Forum and Search --> : Pointers to Functions


Strogian
07-12-2001, 01:19 PM
Okay, I just got to the "Pointers to Functions" section in this C book here, and it's somewhat confusing to me. Could anyone help me with this stuff? (a good website would be fine too =) The book gives a program as an example, and here are some parts of it:

Here is the function prototype of qsort:

void qsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));


And here is the call to qsort:

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


Now, in the prototype, when do we know that the argument should be a function? Is it just when you have the argument parentheses next to a? Also, in that call, (the first three arguments are irrelevant, btw) how does that function casting work? Are the void*'s the same as "void *"?

Later in the chapter, it says that you have to use int (*comp)(void *, void *) instead of int *comp(void *, void *) because the second one would mean a function returning a pointer to an integer. So, how would you pass a function as an argument? (or did they mean that the second version just wouldn't work?)

reklis
07-12-2001, 04:02 PM
The Standard C++ Bible states:

A pointer to a function contains the address of a function; you can call the function through the pointer. You declare a function pointer using this format:

int (*fptr)()

The pointer's name is fptr. This particular pointer points to functions that return int and that accept no arguments. The pointer declaration must match those of the functions to which it points.

The parentheses around the pointer name and its pointer operator (*) override the default operator precedence. Without them, the pointer definition looks like a prototype of a function that returns a pointer to int.

To assign the address of a function to a function pointer, use one of these two formats:

fptr = &TheFunction;
fptr = TheFunction;

The & address-of operator is not requiered, because a function's identifier alone signifies its address rather than a call to the function, which would include an argument list in parentheses.

You call a function through its pointer using one of these formats:

x = (*fptr)();
x = fptr();

The second notation looks just like any other function call. Some programmers prefer to use the first notation, because it documents the fact that the function call is through a pointer rather than to a function of that name.

Here's a pretty simple example:

#include <iostream>
void FileFunc(), EditFunc();
main() {
// Declare a pointer to a function.
void (*funcp)();

// Put an address in the pointer, and
// call the function through the pointer.

funcp = FileFunc;
(*funcp)();

// Put another address in the pointer, and
// Call the function through the pointer.
funcp = EditFunc;
(*funcp)();

return 0;
}

void FileFunc() {
std::cout << "File Function" << std::endl;
}

void EditFunc() {
std::cout << "Edit Function" << std::endl;
}

Personally I think while this is all pretty straight forward, it doesn't really give you a good example of what you'd really want to use it for. Here's a code snippet of a table-driven menu manager:

#include <iostream>
struct Menu {
char *name;
void (*fn)(); // declare
};

// Menu selection function prototypes
void FileFunc();
void EditFunc();
void ViewFunc();
void ExitFunc();

// The menu
Menu menu[] {
{ "File", FileFunc }, // assign...
{ "Edit", EditFunc },
{ "View", ViewFunc },
{ "Exit", ExitFunc }
};

main() {
unsigned sel = 0;

while (sel != 4) {
// Display menu choices
for(int i=0; i<4; ++i)
std::cout << i+1 << ": " << menu[i].name
<< std::endl;
std::cout << "Select: ";

// Get the menu selection from the user
std::cin >> sel;

// Call the requested function through
// a function pointer.
if (sel < 5)
(*menu[sel-1].fn)();
}
}

void FileFunc() {
std::cout << "File Function" << std::endl;
}

void EditFunc() {
std::cout << "Edit Function" << std::endl;
}

void ViewFunc() {
std::cout << "View Function" << std::endl;
}

void ExitFunc() {
std::cout << "Exit Function" << std::endl;
}

I think that's a good, clean example of how function pointers are used. Essentially, they are no different from other pointers, and you can use them the same way. That's the idea. Of course, all of this would have to be adapted for C if that's what you're doing. Check these sites for more details:
http://www.inquiry.com/techtips/cpp_pro/10min/10min0300.asp http://www.newty.de/CCPP/FPT/em_fpt.html http://www.cs.kau.se/~jorgen/courses/dsa/tutorial/funcptr.html http://www.maths.cam.ac.uk/undergrad/tripos/catam/ccatsl/manual/node34.html

------------------
Advocate of the Sharky (Ultra) High-Resolution Club [SHRC (http://www.sharkyforums.com/ubb/Forum17/HTML/005121.html)]
main(i){putchar(341513875>>(i-1)*5&31|!!(i<6)<<6)&&main(++i);}

[This message has been edited by reklis (edited July 12, 2001).]

biosx
07-12-2001, 09:44 PM
What is the C++ bible that you referred to?

I know the C Bible (K&R), but what is the C++ Bible?

------------------
## root is the greed of all evil ##

/* Navi Specs */
Abit KT7-RAID
Duron 800 @ 1GHz
Geforce 2 GTS
512MB Micron/Crucial SDRAM
SB Live! 5.1 w/ Live! Drive
Maxtor ATA100 40GB
Pioneer 16x DVD
HP 9300 series CD-RW
Netgear FA311 NIC
Win2k Server / Linux Mandrake 8.0
Sony Multiscan 17SF (shut up, I know it's old)

Zoma
07-12-2001, 10:25 PM
Not sure what book he's refering to, but the C++ equivalent to K & R is "The C++ Programming Language," by Bjarne Stroustrup.

Just think of a pointer to a function like any other pointer. A function has a location in memory, just like a variable or anything else. That's the important thing to remember, since it will usually keep you out of trouble.

reklis
07-13-2001, 01:44 AM
Originally posted by biosx:
What is the C++ bible that you referred to?

The Standard C++ Bible: http://www.amazon.com/exec/obidos/ASIN/0764546546/qid=994999556/sr=2-1/ref=aps_sr_b_1_1/107-8190328-7322938

------------------
Advocate of the Sharky (Ultra) High-Resolution Club [SHRC (http://www.sharkyforums.com/ubb/Forum17/HTML/005121.html)]
main(i){putchar(341513875>>(i-1)*5&31|!!(i<6)<<6)&&main(++i);}

biosx
07-13-2001, 02:23 AM
lol, it's called The Standard C++ Bible.

Thanks guys, I'll look into those books (esepcially the Stroustrup one)


------------------
## root is the greed of all evil ##

/* Navi Specs */
Abit KT7-RAID
Duron 800 @ 1GHz
Geforce 2 GTS
512MB Micron/Crucial SDRAM
SB Live! 5.1 w/ Live! Drive
Maxtor ATA100 40GB
Pioneer 16x DVD
HP 9300 series CD-RW
Netgear FA311 NIC
Win2k Server / Linux Mandrake 8.0
Sony Multiscan 17SF (shut up, I know it's old)

reklis
07-13-2001, 11:15 AM
I have the Stroustrup book, and I found it very helpfull at first. Now, however, I find that the Standard C++ Bible is a better desktop reference and a quicker source of information. I highly recommend both of them. If you buy online, you need to know about http://www.bookpool.com

------------------
Advocate of the Sharky (Ultra) High-Resolution Club [SHRC (http://www.sharkyforums.com/ubb/Forum17/HTML/005121.html)]
main(i){putchar(341513875>>(i-1)*5&31|!!(i<6)<<6)&&main(++i);}

[This message has been edited by reklis (edited July 13, 2001).]