[prog] ncurses menu code

Laurel Fan laurel at sdf.lonestar.org
Fri Jul 30 09:12:52 EST 2004


No snipping because it makes more sense (what sense it does) if it's
all together.  Comments below..

On Fri, Jul 30, 2004 at 10:00:30AM -0500, ed orphan wrote:
> There's a line of code in the Ncurses Programming HOWTO
> I need help understanding. It's the last example in
> the chapter on menus, example 24, Menu User Pointer Usage.
> In the switch,  
>    case 10:  /* Enter */
>    {    ITEM * cur;     pointer to a menu item declared
>         void (*p) (char  * );   pointer declared to a function that
>                  returns void and has a char pointer as an argument.
>         cur = current_item( my_menu );
>                  current_item returns a pointer to the current item in
>                  the menu called my_menu.
>         p = item_userptr( cur );
>                  Assigning the function item_userptr( cur ) to the
>                  function pointer p.  ( why I have no idea ).
>                  All the man file says about item_userptr is that:
>                  "Every menu item has a field that can be used to
>                   hold application-specific data". item_userptr 
>                   retrieves that field.

Actually, I think it assigns the function returned by item_userptr to
the function pointer p.

If it was assigning item_userptr to p it would be more like:

p = item_userptr;

because function pointers can't have their arguments already supplied.

>         p( ( char *)item_name( cur ) );
>                 Dah?  What is this?
>                 I know that item_name returns the name part of the
>                 the given item and is defined as:
>                 const char *item_name(const ITEM *item)
>                 What does this statement do? 

This calls the function pointed to by p (in other words, the function
retrieved by item_userptr).  The return value of item_name is the
argument used when calling the function pointed to by p.

>                 Is there a simpler, more understandable method to
>                 get the same job done?

Without seeing the rest of the code, it's hard to tell.  Almost any
time you make use of void * and function pointers, C code rapidly gets
less understandable.

Overall, I get the idea that what is happening is:

We want menu items to do something, so each menu item must describe
what it does.  One way of describing something to do is to store a
pointer to a function, so that's what we do here.  item_userptr is
being used to retrieve this stored function.  p is used as a temporary
variable and an implicit cast (item_userptr returns void*) simply for
better readability (yes, it actually would be even harder to read
without p).

I hope that made more sense (or at least more sense than the code).

Tangent (probably more detail than you want): The reason this is so
messy is because there is a idiom called "functional programming" in
which functions are first class objects (ie. you can pass them around,
combine them, and operate on them just like you would on an int in C
or a class in C++).  This snippet of code seems to want to act like
functional, but this isn't very well supported in C.  Pretty much the
only way to do something like this is with function pointers, which
are kind of a hack, and look very messy to those who are not used to
them.



-- 
laurel at sdf.lonestar.org
http://dreadnought.gorgorg.org


More information about the Programming mailing list