Google
 
Webnews.only-4-geeks.com
Interesting places
news.only-4-geeks.com Forum Index » CGoto page 1, 2, 3  Next

Some issue with pointers

 
Jump to:  
 
Marco Trapanese
PostPosted: Mon Jun 30, 2008 4:56 pm    Post subject: Some issue with pointers
       
Hello,

I need some help to understand what I'm doing :)

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).

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.

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"};

ot invoke:

void myfunc();

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

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?

Thank you and I apologize for my poor English
Marco / iw2nzm
 

 
Ben Bacarisse
PostPosted: Mon Jun 30, 2008 9:00 pm    Post subject: Re: Some issue with pointers
       
Marco Trapanese <marcotrapaneseNOSPAM@gmail.com> writes:

Quote:
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?

Quote:
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.

Quote:
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].

Quote:
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).

Quote:
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.
 

 
Marco Trapanese
PostPosted: Tue Jul 01, 2008 7:17 am    Post subject: Re: Some issue with pointers
       
Ben Bacarisse ha scritto:

Quote:
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?

You're right, it's my fault. I'm not so experienced (yet) in this kind
of thing!


Quote:
Function pointers are "special" in that there is no guarantee in C
that you can convert a void * to function pointer (nor vice versa).

What a pity! :)


Quote:
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.

So, are you suggesting to add in the union a pointer for each type I
need, aren't you? Or at least, the function pointer because is treated
differently.


Quote:
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].

Ok, I was trying to access directly from ptr with a cast. But it's more
readable you solution.


Quote:
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).


Ok, this answer my first question above. I read the 'type' value and use
the correct union entry. The others will be ignored.


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

I got it.

Thank you a lot for the time you spent!

Marco / iw2nzm
 

 
Marco Trapanese
PostPosted: Tue Jul 01, 2008 8:09 am    Post subject: Re: Some issue with pointers
       
Ben Bacarisse ha scritto:

Quote:
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;


Please, consider this short code:


char mypar[3];
void myfunc();

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


Ok, now I want to initialize this struct:

const menu_t mn_mnu = {
{"Main Menu", "Menu"},
MIT_FUNCTION,
0,
{mypar}
};


It successfully compiles. Please note that the function pointer
declaration in Dynamic C is slightly different from standard-C. The
syntax is the same: returntype (*name)(); also for functions with
parameters.

Now I want to initialize the second (and eventually the third) element
of the union. How should I do?

{, myfunc}
{0, myfunc}
{NULL, myfunc}

None of these works. The compiler screams loud a lot of errors.
I'm googled on this but I didn't find an example.

Bye
Marco / iw2nzm
 

 
Ben Bacarisse
PostPosted: Tue Jul 01, 2008 11:56 am    Post subject: Re: Some issue with pointers
       
I'll keep my replies to this thread. In the other reply you asked a
question. Imagine that I relied to it "yes".

Marco Trapanese <marcotrapaneseNOSPAM@gmail.com> writes:

Quote:
Ben Bacarisse ha scritto:

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;


Please, consider this short code:

char mypar[3];
void myfunc();

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


Ok, now I want to initialize this struct:

const menu_t mn_mnu = {
{"Main Menu", "Menu"},
MIT_FUNCTION,
0,
{mypar}
};


It successfully compiles. Please note that the function pointer
declaration in Dynamic C is slightly different from standard-C. The
syntax is the same: returntype (*name)(); also for functions with
parameters.

Now I want to initialize the second (and eventually the third) element
of the union. How should I do?

{, myfunc}
{0, myfunc}
{NULL, myfunc}

You need to either

(1) Use C99 designated initialiser syntax:

{ .fp = myfunc }

(2) Let the compiler complain about the type-mismatch (if it works):

{ myfunc }

(3) Convert to void * (again, if that is permitted):

{ (void *)myfunc }

You don't loose anything this way. In your method, you were still
going to have to initialise a void * with a function pointer which is
what the above does (with C99 you can only initialise the first
element of a union).

Of course, you can do it at runtime (mn_mnu.ptr.fp = myfunc;) but then
you can have the menu as const.

--
Ben.
 

 
Marco Trapanese
PostPosted: Tue Jul 01, 2008 1:52 pm    Post subject: Re: Some issue with pointers
       
Ben Bacarisse ha scritto:

Quote:
(1) Use C99 designated initialiser syntax:

{ .fp = myfunc }


This one doesn't work. I bet Dynamic C is not C99 compliant.


Quote:
(2) Let the compiler complain about the type-mismatch (if it works):

{ myfunc }

(3) Convert to void * (again, if that is permitted):

{ (void *)myfunc }

These works, or at least the compiler says nothing about.

Now I have to verify that myfunc is actually assigned to fp and not to vp.


Quote:
You don't loose anything this way. In your method, you were still
going to have to initialise a void * with a function pointer which is
what the above does (with C99 you can only initialise the first
element of a union).

Of course, you can do it at runtime (mn_mnu.ptr.fp = myfunc;) but then
you can have the menu as const.


Yeah, I want to declare them as constants to save code space.

Thanks again
Marco / iw2nzm
 

 
Marco Trapanese
PostPosted: Tue Jul 01, 2008 1:56 pm    Post subject: Re: Some issue with pointers
       
Marco Trapanese ha scritto:

Quote:
Now I have to verify that myfunc is actually assigned to fp and not to vp.


Verified. Great! It works like a charm.

Marco / iw2nzm
 

 
Ben Bacarisse
PostPosted: Tue Jul 01, 2008 1:59 pm    Post subject: Re: Some issue with pointers
       
Marco Trapanese <marcotrapaneseNOSPAM@gmail.com> writes:

Quote:
Ben Bacarisse ha scritto:

(1) Use C99 designated initialiser syntax:

{ .fp = myfunc }

This one doesn't work. I bet Dynamic C is not C99 compliant.

Shame. This is one of the nice part of C99.

Quote:
(2) Let the compiler complain about the type-mismatch (if it works):

{ myfunc }

(3) Convert to void * (again, if that is permitted):

{ (void *)myfunc }

These works, or at least the compiler says nothing about.

Now I have to verify that myfunc is actually assigned to fp and not
to vp.

You do realise that they are, in effect, one and the same? You can't
have both fp and vp assigned different values at the same time. That
is what the union is for.

--
Ben.
 

 
Marco Trapanese
PostPosted: Tue Jul 01, 2008 2:13 pm    Post subject: Re: Some issue with pointers
       
Ben Bacarisse ha scritto:

Quote:
You do realise that they are, in effect, one and the same? You can't
have both fp and vp assigned different values at the same time. That
is what the union is for.


You're right again. I didn't realized that. But now I should have
understood: all union items share the same address so they are "the
same" thing.

Ok, I learned something new today :)

Marco / iw2nzm
 

 
Keith Thompson
PostPosted: Tue Jul 01, 2008 2:59 pm    Post subject: Re: Some issue with pointers
       
Marco Trapanese <marcotrapaneseNOSPAM@gmail.com> writes:
Quote:
Ben Bacarisse ha scritto:
You do realise that they are, in effect, one and the same? You can't
have both fp and vp assigned different values at the same time. That
is what the union is for.

You're right again. I didn't realized that. But now I should have
understood: all union items share the same address so they are "the
same" thing.
[...]


Well, sort of. They're not really "the same" thing; they're different
things that happen to share the same space.

Imagine that you work the day shift, and you share an office with
someone who works the night shift. You're never in the office at the
same time. You both have the same address, but you're two different
people. And somebody who wants to visit one of you need to know what
time it is to know which one of you to expect.

As for initialization, an ordinary C90-style initializer for a union
simply initializes the first declared member. For example:

int main(void)
{
union foo {
int x;
char *s;
};

union foo obj1 = { 42 }; /* ok, sets obj1.x to 42 */
union foo obj2 = { "hello" }; /* wrong, tries to set x to "hello" */

return 0;
}

C99 lets you choose which member you want to initialize, but since you
apparently want to initialize the first one anyway, you don't need
that feature.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 

Page 1 of 3 .:. Goto page 1, 2, 3  Next

Google
 
Webnews.only-4-geeks.com

Windows Update | C++ | C | PHP | JavaScript | Photoshop | Programming | Windows 2000 | Python | Windows XP | Object | Flash | Flash - ActionScript | Paint Shop Pro | Excel | PowerPoint | Access | Word | Windows 98 | Internet Explorer 6.0 | CorelDraw12 | Java | XML | asm x86 | Linux Mandrake | Linux RedHat | Outlook |  | news from newsgroups |_ | s

Web Templates

Awesome Website Templates ©

katalog firm noclegi w bieszczadach projekty domów parterowych Bick tanie alkomaty