Re: Some issue with pointers



Marco Trapanese <marcotrapaneseNOSPAM@xxxxxxxxx> writes:

I'm writing code for an embedded system and I need to create a
navigable menu system. I'm going to use these structures:

typedef struct {
char *name[2];
int type;
int num_param;
void *ptr;
} menuitem_t;

typedef struct {
char *name[2];
int num_items;
menuitem_t *items;
} menu_t;


The latter defines each menu or submenu with a name, a number of items
and a pointer to the items structure.

The former defines each menu item with a name, a type (see below) the
number of parameters - if any - and finally a generic pointer (see
below again).

I can't see why you'd have two. I'd merge them like this:

typedef struct menu {
char *name[2];
int type;
int num_param;
union {
void *vp;
struct menu *items;
} ptr;
} menu_t;

It must be simpler to have only one type (in the C sense) for menu
items, surely?

In this way I can generate menus of any complexity and very
flexible. The void pointer should point to another menu_t struct if
the item leads to a submenu, to an array if it leads to a parameter
list. But it could also leads to a function if the selection of this
item needs an action to be executed.

Function pointers are "special" in that there is no guarantee in C
that you can convert a void * to function pointer (nor vice versa).
Your implementation may offer this as an extension, but if you use a
union, you can add a function pointer type and not have any
portability worries.

Actually I have two questions:

1) I can't cast correctly the void *ptr. Let's say I want to access to:

char *par[] = {"First", "Second"};

Let's say that ptr got set like this: 'ptr = par;'. ptr is then a
char ** in disguise so simply writing:

char **strings = ptr;

would let you access strings[0] and strings[1].

ot invoke:

void myfunc();

Please, may you help me to understand how to cast and then to use that
pointer in these cases?

It is easiest not to use a cast. Just assign ptr to a variable of the
right type and off you go.

However, since this requires an extension to standard C, you might
want to consider using a union containing an element for each pointer
type you need. This means you don't have to reply on converting a
void * to a function pointer and it keeps the code very clean (at the
expense of a messy union).

2) It would be nice if I can know the path the user is following. For
example:

mainmenu -> seconditem -> firstitem

where each of these entities are menu_t structs.
How would you implement such a dynamic path?

I'd use a stack, probably implemented as a linked list.

--
Ben.
.



Relevant Pages

  • Re: (void**)&ppval
    ... a sort of "generic data pointer type". ... returned from mallochas type "void *", so that it can point to ... void *tmp; ... T *ptr; ...
    (comp.lang.c)
  • Re: invalid pointer adress
    ... >> pointer causes the program to exit with a core dump. ... struct s2{void *p;}; ... int leseExterneHinweise_masch_storno ... typedef struct s_AusdatFeldbeschreibung ...
    (comp.lang.c)
  • Re: Generic linked list with internal storage?
    ... there are some *major advantages* to using a void* in a generic linked ... it allows you to store a void pointer as data. ... prohibits arbitrary lists to be sorted according to arbitrary ordering ... in some other struct containing the user data as well. ...
    (comp.lang.c)
  • Re: A C Adventure: your comments are welcome
    ... void * usrRightSegment; ... That is a string is a binary tree of segments, ... struct inside a struct either as the thing itself or as a pointer ... because C makes it easy to change pointer type. ...
    (comp.lang.c)
  • [PATCH] Make kunmap_atomic() harder to misuse
    ... takes takes a pointer to within the page itself. ... struct page * but it is not a void * (verified by trying to convert it ... -static inline void kunmap_atomic ...
    (Linux-Kernel)