473,837 Members | 1,517 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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
Jun 30 '08
19 1305
Keith Thompson ha scritto:
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.
Got it.

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.
mmm, I guess I can't have two items in a union of the same type, can I?
The compiler will know what is the item I'm going to initialize if they
are different. In effect, it doesn't make any sense to use a union with
two fields of the same type.

Marco / iw2nzm

Jul 1 '08 #11
Marco Trapanese <ma************ ******@gmail.co mwrites:
Keith Thompson ha scritto:
>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.

Got it.

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

mmm, I guess I can't have two items in a union of the same type, can I?
The compiler will know what is the item I'm going to initialize if
they are different. In effect, it doesn't make any sense to use a
union with two fields of the same type.
It doesn't work like that -- the type of the expression used to
initialise a union has no effect in choosing which member is
initialised. When a union is initialised, it is the first
member that is chosen unless (in C99 code) a designator is given:

union eg1 {
double d;
int i;
} example1 = { 1.2 };

This initialises the double, and this:

union eg2 {
int i;
double d;
} example2 = { 1.2 };

initialises the int (converting the 1.2 in the process). You can have
several members of the same type but although that would be pointless
it has no effect on the compiler initialises the union.

--
Ben.
Jul 1 '08 #12
Ben Bacarisse ha scritto:
union eg1 {
double d;
int i;
} example1 = { 1.2 };

This initialises the double, and this:

union eg2 {
int i;
double d;
} example2 = { 1.2 };

initialises the int (converting the 1.2 in the process). You can have
several members of the same type but although that would be pointless
it has no effect on the compiler initialises the union.

I'm feeling a bit stupid but I don't understand the whole thing.
Why in my code I can initialize the function pointer that is the second
element?

Is it related to C90/C99 stuff?

Marco / iw2nzm
Jul 1 '08 #13
Ben Bacarisse ha scritto:
typedef struct {
char *name[2];
int type;
union {
void *vp;
void (*fp)();
struct menu_t *items;
} ptr;
} menu_t;

Hello again, this time I'm trying to initialize the union with the third
entry, that is another menu_t struct.

const menu_t mn_menu = {
{"Main Menu", "Menu"},
MIT_SUBMENU,
{{mn_setup, mn_about}}
};

Where mn_setup and mn_about are other two const structs previously
defined. The compilers complains about type mismatch. I thought I was
able to initialize this damn unions but I was wrong.

It works with an array, it works with a function pointer why doesn't
work with a struct?

Marco / iw2nzm
Jul 1 '08 #14
Marco Trapanese <ma************ ******@gmail.co mwrites:
Ben Bacarisse ha scritto:
union eg1 {
double d;
int i;
} example1 = { 1.2 };
This initialises the double, and this:
union eg2 {
int i;
double d;
} example2 = { 1.2 };
initialises the int (converting the 1.2 in the process). You can
have
several members of the same type but although that would be pointless
it has no effect on the compiler initialises the union.


I'm feeling a bit stupid but I don't understand the whole thing.
Why in my code I can initialize the function pointer that is the
second element?

Is it related to C90/C99 stuff?
I had to go back up the thread to see what you're talking about:

union {
void *vp;
void (*fp)();
struct menu *items;
} ptr;

This was part of a larger structure. You initialized ptr to {mypar},
where mypar is the name of an array of char.

The result of evaluating ``mypar'', of type char*, was implicitly
converted to void* and used to initialize ptr.vp. (This indirectly
assigns a value to the space occupied by ptr.fp and ptr.items, but
accessing those members is unsafe.)

Any initialization of this union, unless you use a C99 designated
initializer, is going to initialize ptr.vp.

If this doesn't match your understanding, can you post a small example
that illustrates the issue?

--
Keith Thompson (The_Other_Keit h) ks***@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"
Jul 1 '08 #15
Marco Trapanese <ma************ ******@gmail.co mwrites:
Ben Bacarisse ha scritto:
>typedef struct {
char *name[2];
int type;
union {
void *vp;
void (*fp)();
struct menu_t *items;
} ptr;
} menu_t;


Hello again, this time I'm trying to initialize the union with the
third entry,
You can't. You don't have a C99 compiler so any initialiser you use
will be used to initialise the first union member. Always the first.
OK?

In fact, given that you can't use the union in the way it is intended
(C99 designated initialisers) I advice you don't use a union. It
would be fine if you set the union at runtime, but bending the type
rules by initialising always the first element is probably more
problematic than converting everything to and from a void *. There
are machines on which this breaks:

int i;

union {
void *vp;
int *ip;
} u = { &i };

followed by an access of, say, u.ip[0]. It may be best just to force
the conversion to and from a single void * all the time.
that is another menu_t struct.

const menu_t mn_menu = {
{"Main Menu", "Menu"},
MIT_SUBMENU,
{{mn_setup, mn_about}}
};

Where mn_setup and mn_about are other two const structs previously
defined. The compilers complains about type mismatch. I thought I was
able to initialize this damn unions but I was wrong.
You can, but you need a pointer, not another set of {}s. You really
need to go over this in a C textbook -- you can't learn this by trial
and error. For the record, you do it like this:

struct menu_t submenuitem = {mn_setup, mn_about};

const menu_t mn_menu = {
{"Main Menu", "Menu"},
MIT_SUBMENU,
&submenuitem
};

You'll be thrilled that C99 can do this directly with a compound
literal like this:

const menu_t mn_menu = {
{"Main Menu", "Menu"},
MIT_SUBMENU,
&(struct menu_t){mn_setu p, mn_about};
};

Ask you compiler vendor to support C99!
It works with an array, it works with a function pointer why doesn't
work with a struct?
Because you need a pointer and both arrays and functions get converted
to pointers in this context -- structs don't.

--
Ben.
Jul 1 '08 #16
On Tue, 01 Jul 2008 17:52:15 +0200, Marco Trapanese
<ma************ ******@gmail.co mwrote:
>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.

>(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.
Since fp and vp overlap (occupy the same memory), how do propose to
accomplish this?
Remove del for email
Jul 2 '08 #17
On Tue, 01 Jul 2008 19:56:49 +0200, Marco Trapanese
<ma************ ******@gmail.co mwrote:
>Ben Bacarisse ha scritto:
>union eg1 {
double d;
int i;
} example1 = { 1.2 };

This initialises the double, and this:

union eg2 {
int i;
double d;
} example2 = { 1.2 };

initialises the int (converting the 1.2 in the process). You can have
several members of the same type but although that would be pointless
it has no effect on the compiler initialises the union.


I'm feeling a bit stupid but I don't understand the whole thing.
Why in my code I can initialize the function pointer that is the second
element?
You can't. You are initializing the void* that occupies the same
space as your function pointer. You also don't know if the void*
representation is acceptable as a function pointer.
>
Is it related to C90/C99 stuff?
No. The only difference between C90 and C99 is that in C99 you can
specify which member of the union you want to initialize.
Remove del for email
Jul 2 '08 #18
Ben Bacarisse ha scritto:
You can't. You don't have a C99 compiler so any initialiser you use
will be used to initialise the first union member. Always the first.
OK?

Ok.
I was confused because in your first post on this thread you wrote:

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;

So I assumed I can use (and initialize) both the void pointer and the
menu_t struct.

So I must return to use two different structs.

In fact, given that you can't use the union in the way it is intended
(C99 designated initialisers) I advice you don't use a union. It
would be fine if you set the union at runtime,
Yeah, but this is code space consuming. It could be done for few
entries, but it isn't so elegant ;-)

but bending the type
rules by initialising always the first element is probably more
problematic than converting everything to and from a void *. There
are machines on which this breaks:

int i;

union {
void *vp;
int *ip;
} u = { &i };

followed by an access of, say, u.ip[0]. It may be best just to force
the conversion to and from a single void * all the time.

Ok, but given that I need three different types of pointers (generic
void, function, struct) I'll set them at runtime or it will be better to
separate each one - at the cost of more memory of course.

You can, but you need a pointer, not another set of {}s. You really
need to go over this in a C textbook -- you can't learn this by trial
and error.
I'll do that.

Ask you compiler vendor to support C99!
Perhaps the pay version of the compiler does, but it costs several
thousand dollars...

Because you need a pointer and both arrays and functions get converted
to pointers in this context -- structs don't.
Ok, these limitations are beyond my knowledge. I search another way to
build my menu system.

I thank you very much for your patience
Marco / iw2nzm

Jul 2 '08 #19
Marco Trapanese <ma************ ******@gmail.co mwrites:
Ben Bacarisse ha scritto:
>You can't. You don't have a C99 compiler so any initialiser you use
will be used to initialise the first union member. Always the first.
OK?


Ok.
I was confused because in your first post on this thread you wrote:
>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;

So I assumed I can use (and initialize) both the void pointer and the
menu_t struct.

So I must return to use two different structs.
Oh dear. We've gone off the rails here! Your code will get very
messy if you have two menu structs just because at some point you
need one of two types of pointer in it. It will get worse if you have
three types, and so on.

If you had C99, a union is the simplest way to build your menus using
static initialisers -- that is why I suggested it. You don't have C99
so your options are:

(a) One menu struct with a data pointer of type void *. The only down
side of this if that you keep having to convert between the pointer
types. This is not hard and has the advantage of being about as
portable you can get. You can continue to use static initialisation.

(b) Use a union to avoid some of the type conversions. This can have
portability problems because some type conversion are essential (on
some systems). Had I know that you wanted to use static
initialisation for all the menus and that you did not have C99, I
would not have suggested a union. Just ditch that idea.

I *still* would have suggested having only one menu struct -- with a
void * data member.

<snip>
Ok, but given that I need three different types of pointers (generic
void, function, struct) I'll set them at runtime or it will be better
to separate each one - at the cost of more memory of course.
Your choice. You can use a struct with just a void * and use static
initialisation, or a struct with union and use some run-time member
setting.

<snip>
Ok, these limitations are beyond my knowledge. I search another way to
build my menu system.
Just forget I suggested a union! Keep the idea of simplifying it to
one structure; keep the static initialisation. You can get the best
of all worlds that way. Some people use macros to wrap up the casts:

typedef struct menu {
char *name[2];
int type;
int num_param;
void *data;
} menu_t;

#define SUBMENU_PTR(m_p tr) ((menu_t *)(m_ptr)->data)
#define STRINGS_PTR(m_p tr) ((char **)(m_ptr)->data)
#define ACTION_PTR(m_pt r) ((menu_function *)(m_ptr)->data)

--
Ben.
Jul 2 '08 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
1585
by: Ken | last post by:
I am familiar with C and Java, I would like to use a style that I have become accustomed to in Java with C++ but each time I do this I have name conflict. In the past I have just worked around it by using different names can anyone tell me how to get the following to work: I want to have a class named v3d (vector 3d), it has the following private instance variables... float x, y, z; It has the following public get and set methods:
193
9675
by: Michael B. | last post by:
I was just thinking about this, specifically wondering if there's any features that the C specification currently lacks, and which may be included in some future standardization. Of course, I speak only of features in the spirit of C; something like object-orientation, though a nice feature, does not belong in C. Something like being able to #define a #define would be very handy, though, e.g: #define DECLARE_FOO(bar) #define...
16
2317
by: junky_fellow | last post by:
According to Section A6.6 Pointers and Integers (k & R) " A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage. It is guaranteed that a pointer to an object may be converted to a pointer to an object whose type requires less or equally strict storage alignment and back again without change;...
48
2190
by: yezi | last post by:
Hi, all: I want to record some memory pointer returned from malloc, is possible the code like below? int memo_index; int i,j; char *tmp; for (i=0;i<10;i++){
4
1664
by: mathieu | last post by:
Hello, I would like implement a nice way to work around the array of references issue in C++. What do usually people do ? Do you maintain a separate factory/pool of elements as part of the API ? So in my example (*) I would need to either : 1. allocate on the heap (and then fragment memory): void fill(A *array) {
1
1923
by: Ted | last post by:
I managed to get it installed OK, along side MS Visual Studio 2005 (with which I received it). During the install, I made sure I installed everything. I have developed a number of applications using MySQL v 5 and PostgreSQL, but I have not worked with MS SQL. Playing with it after installing it, and running through several tutorials, I generally like what I see, but there are a few issues (so far - I am sure others will crop up as...
25
4832
by: al pacino | last post by:
hi , whats the issue with the following declaration, is it correct and what exactly is happening here. int main() { //..... int* ptr=10; // i suppose ptr is pointing to the memory location which stores the value 10.
2
970
by: mabond | last post by:
Hi I want to begin researching methods for a particular problem I have and would welcome some pointers, or info if anyone has had the same issue. At my place of work we have a display of data in the form of a java applet. The data displayed relates to the performance of our workforce but is provided by a third party and is only seen by us on screen. In other words there is no raw data file received and no means of "ftp" to access the...
8
1423
by: John Nagle | last post by:
The Python documentation for "str" says "str() : Return a string containing a nicely printable representation of an object." However, there's no mention of the fact that "str" of a Unicode string with non-ASCII characters will raise a conversion exception. The documentation (and several Python books) seem to indicate that "str" will produce some "printable representation" for anything, not raise an exception. I know, it was proposed...
0
9844
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9683
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10883
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10578
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9409
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
7006
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5851
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4477
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4049
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.