473,411 Members | 2,030 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

Intializing struct containing an union


I have a menu_item structure containing an union.
func is used if the menu item should use a callback,
and submenu if a popupmen should be shown.

struct menu_item {
enum { function, popup } type;
union {
int (*func)(int);
struct menu_item *submenu;
} action;
};

The problem is that I want to use an initializer to
initialize this structure.
But if I understood what I read in the FAQ right, you can't initialize
the unions in C89, only in C99 with ``designated initializers''.
I could use the C99 feature (I think, I haven't really checked it out),
but I usually try to only code in C89, so I wonder if there is some
good way to solve this in C89 (not absolutely neccessary though).
I could of course just remove the union and only use two regular
variables, func and submenu, and use just one of them depending on
the types.
Or how about using a void pointer, and casting it between a fuction
pointer or a structure pointer?

Any comments are appreciated!

/Michael Brennan

Jul 24 '06 #1
4 2558
On Mon, 24 Jul 2006 12:08:09 GMT, Michael Brennan
<br************@gmail.comwrote in comp.lang.c:
>
I have a menu_item structure containing an union.
func is used if the menu item should use a callback,
and submenu if a popupmen should be shown.

struct menu_item {
enum { function, popup } type;
union {
int (*func)(int);
struct menu_item *submenu;
} action;
};

The problem is that I want to use an initializer to
initialize this structure.
But if I understood what I read in the FAQ right, you can't initialize
the unions in C89, only in C99 with ``designated initializers''.
You understand it incorrectly. In C89 you may initialize the first
member of a union. You may not initialize any other member.
I could use the C99 feature (I think, I haven't really checked it out),
but I usually try to only code in C89, so I wonder if there is some
good way to solve this in C89 (not absolutely neccessary though).
I could of course just remove the union and only use two regular
variables, func and submenu, and use just one of them depending on
the types.
Or how about using a void pointer, and casting it between a fuction
pointer or a structure pointer?
There is absolutely no defined conversion whatsoever between pointers
to functions of any signature, and pointers to objects of any type.
There are platforms where the two are of different sizes.

Do you have more than 1,000,000 of these? If not, or even if so,
consider changing it to:

struct menu_item
{
int (*func)(int);
struct menu_item *submenu;
}

And initialize like this:

struct menu_item top_menu_tree [] =
{
{ func1, NULL },
{ NULL, file_menu_tree },
{ NULL, edit_menu_tree },
{ NULL, search_menu_tree },
{ NULL, tool_menu_tree },
{ show_help, NULL }
};

The enumerator is no longer needed, a simple test for NULL will do.

Consider that on typical desktop platforms today (i.e., 32-bit),
sizeof (int) == sizeof (void*) == sizeof (int (*)(int). Even if your
compiler provides an option to instantiate enumerated types in the
smallest integer type that can hold the value, it is quite possible
that alignment padding will make your structure as large as mine.

And even if your struct ends up, let's say, 3 bytes shorter than mine,
how many of them will your program actually have? What price
correctness and portability?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 25 '06 #2
In article <JK******************@newsb.telia.net>
Michael Brennan <br************@gmail.comwrote:
>
I have a menu_item structure containing an union.
func is used if the menu item should use a callback,
and submenu if a popupmen should be shown.

struct menu_item {
enum { function, popup } type;
union {
int (*func)(int);
struct menu_item *submenu;
} action;
};

The problem is that I want to use an initializer to
initialize this structure.
But if I understood what I read in the FAQ right, you can't initialize
the unions in C89, only in C99 with ``designated initializers''.
More precisely, you can only initialize the *first* union member.
So if you have a function fn:

int fn(int);
struct menu_item m_fn = { function, { fn } };

which works in both C89 and C99; but if you have a popup "pu" you
need C99's:

struct menu_item pu = { popup, { .submenu = &m_fn } };

There is no completely-satisfactory solution to this problem, but
there is a method that, if you can use it at all, is likely to
work on "real implementations". Namely, write variants of the
"struct" that have each of the union members "first". In this
case:

enum menu_item_type { function, popup };

struct menu_item_if_function {
enum menu_item_type type; /* should be "function" */
union {
int (*func)(int);
struct menu_item *submenu;
} action;
};
struct menu_item_if_popup {
enum menu_item_type type; /* should be "popup" */
union {
struct menu_item *submenu;
int (*func)(int);
} action;
};

Now you can do this:

int fn(int);
struct menu_item_if_function m_fn = { function, { fn } };
struct menu_item_if_popup m_pu = { popup, { &m_fn } };

At some point, you pick one of the variants (arbitrarily) to be
the "main" one for use in the code. Let us say that in this case
you choose "menu_item_if_function" (which you might then rename
to remove the "_if_function" suffix, but for the moment I will
leave it in). Then you can make an array of pointers to the
various initialized objects (m_fn and m_pu above), and cast the
"wrong type" pointers (and hope very hard that the compiler has
not done bizarre things, so that this actually works):

struct menu_item_if_function *array[] = {
&m_fn,
(struct menu_item_if_function *)&m_pu,
NULL
};
>Or how about using a void pointer, and casting it between a fuction
pointer or a structure pointer?
This fails on some Real Implementations, where "int (*)(int)" is
128 bytes long (function pointers have a lot of stuff in them) but
"void *" is only 32 bytes long (data pointers have only a little
stuff in them).

The "multiple variants of the struct" trick is much more likely to
work: it depends only on the compiler making the layout of each
struct-containing-a-union independent of the order of the union
members. By having all the same members in each "sub-union", we
guarantee that they all have *enough* room (and alignment) for
*all* their members, and they should generally all have the same
size and layout. Then, since all the "struct"s have the same
members (in terms of size and layout), all the "struct"s should
have the same alignment and so on as well.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 25 '06 #3
Chris Torek <no****@torek.netwrites:
[...]
This fails on some Real Implementations, where "int (*)(int)" is
128 bytes long (function pointers have a lot of stuff in them) but
"void *" is only 32 bytes long (data pointers have only a little
stuff in them).
Not that it's relevant to your point, but do you really mean 128 and
32 bytes rather than bits?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 25 '06 #4
>Chris Torek <no****@torek.netwrites:
>This fails on some Real Implementations, where "int (*)(int)" is
128 bytes long (function pointers have a lot of stuff in them) but
"void *" is only 32 bytes long (data pointers have only a little
stuff in them).
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.orgwrote:
>Not that it's relevant to your point, but do you really mean 128 and
32 bytes rather than bits?
Not really sure; I was thinking of the AS/400, where pointers are
"ridiculously large".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 7 '06 #5

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

Similar topics

4
by: James Roberge | last post by:
I am having a little trouble getting my union/struct to work correctly. I am creating a struct that will contain information about the status of various Z80 cpu registers in an emulator i am...
2
by: Peter Dunker | last post by:
Hi, I will write ANSI C89. Is the following struct defenition correct ? I wrote it with VC6(Windows IDE) and at first no Problem. As I changed a compiler switch to 'no language extension', the...
14
by: indigodfw | last post by:
Greetings from India I would like to know the rationale on allowing structs to be assigned (using = operator) and not allowing equality operator ( == operator) on them. The compiler when it...
2
by: Jason Curl | last post by:
Hello C Group, From what I remember, it is implementation dependent the way that a compiler may order bitfields in a struct. In the example program I give, Solaris Sparc gives one result, Intel...
3
by: cody | last post by:
I got a warning from fxcop from the declararation of a struct. the warning: "Structures with explicit layout containing misaligned fields cause crashes on 64 bit platforms" the struct:
32
by: Weiguang Shi | last post by:
Hi, Is there a tool that, given a struct definition, generates a function that parses binary data of this struct and a command that can be used to construct binary data according to...
3
by: Hallvard B Furuseth | last post by:
to find the required alignment of a struct, I've used #include <stddef.h> struct Align_helper { char dummy; struct S align; }; enum { S_alignment = offsetof(struct Align_helper, align) };
4
by: pallav | last post by:
hello, i'm sorry if this is a bit off topic but perhaps some of you here have experience with c++ with lex/yacc and can help me. i wrote a small lexer/parser using lex/yacc. i'm using c++ as...
10
by: Raman | last post by:
Hi All, Is it valid: struct test{ }; I mean, Can we have a struct containing no members? Is this a an
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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,...
0
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...

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.