By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,852 Members | 2,219 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,852 IT Pros & Developers. It's quick & easy.

Unnamed members

P: n/a
The project I'm currently on makes heavy use of unnamed structures to
represent an "object hierarchy" of a sort.

E.g.

struct BaseObject
{
int aMember;
int anotherMember;
// etc.
};

struct GameObject
{
struct BaseObject;

int yetAnotherMember;
// etc.
};

Doing so facilitates the use of the BaseObject's members, so a
function might be able to do:

void fn(GameObject* g)
{
g->aMember = 4;
g->anotherMember = 6;
g->yetAnotherMember = 839;
}

However, coming from a C++ background myself (in recent history,
anyway), this sort of thing horrifies me on many levels. Even when I
was a C programmer exclusively (almost ten years now past!), I never
saw this functionality used on any actual project.

My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?" I suppose the answer may come down to your
view of object oriented concepts, but even from a purely procedural
point of view, I don't like the idea of not being able to easily
figure out where a member actually lives. Bear in mind that this
method is used substantially, and it is not uncommon for an "object
hierarchy" so-constructed to be 10 levels deep. ...that of course
brings with it its own challenges, but I'm mostly interested in how
"real" C coders view unnamed member variables and their use as
demonstrated above.

thanks for any insight,
-tom!
Jun 23 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
L7
Tom Plunket wrote:
The project I'm currently on makes heavy use of unnamed structures to
represent an "object hierarchy" of a sort.

E.g.

struct BaseObject
{
int aMember;
int anotherMember;
// etc.
};

struct GameObject
{
struct BaseObject;

int yetAnotherMember;
// etc.
};

Doing so facilitates the use of the BaseObject's members, so a
function might be able to do:

void fn(GameObject* g)
{
g->aMember = 4;
g->anotherMember = 6;
g->yetAnotherMember = 839;
}

However, coming from a C++ background myself (in recent history,
anyway), this sort of thing horrifies me on many levels. Even when I
was a C programmer exclusively (almost ten years now past!), I never
saw this functionality used on any actual project.

My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?" I suppose the answer may come down to your
view of object oriented concepts, but even from a purely procedural
point of view, I don't like the idea of not being able to easily
figure out where a member actually lives. Bear in mind that this
method is used substantially, and it is not uncommon for an "object
hierarchy" so-constructed to be 10 levels deep. ...that of course
brings with it its own challenges, but I'm mostly interested in how
"real" C coders view unnamed member variables and their use as
demonstrated above.

thanks for any insight,
-tom!


Although it is similar, it may be different enough for what you want:

#define COMMON_MEMBERS \
const char * name; \
struct info_t info; \
int type \

Which allows for things such as:

typedef base_type {
COMMON_MEMBERS;
} base_t;

typedef list_type {
COMMON_MEMBERS;
size_t nchildren;
base_t *children[MAX];
} list_t;

typedef something_more_involved {
COMMON_MEMBERS;
char storage[255];
unsigned char IP[4];
int valid;
} extended_t;

enum { THING_BASE,
THING_LIST,
THING_EXTEND,
}

And when you want to use it...

base_t * thing;
thing = (base_t *) CAST_TO_THING (THING_LIST);

Jun 23 '06 #2

P: n/a

Tom Plunket wrote:
The project I'm currently on makes heavy use of unnamed structures to
represent an "object hierarchy" of a sort.

E.g.

struct BaseObject
{
int aMember;
int anotherMember;
// etc.
};

struct GameObject
{
struct BaseObject;

int yetAnotherMember;
// etc.
};

Doing so facilitates the use of the BaseObject's members, so a
function might be able to do:

void fn(GameObject* g)
{
g->aMember = 4;
g->anotherMember = 6;
g->yetAnotherMember = 839;
}

However, coming from a C++ background myself (in recent history,
anyway), this sort of thing horrifies me on many levels. Even when I
was a C programmer exclusively (almost ten years now past!), I never
saw this functionality used on any actual project.

My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?" I suppose the answer may come down to your
view of object oriented concepts, but even from a purely procedural
point of view, I don't like the idea of not being able to easily
figure out where a member actually lives. Bear in mind that this
method is used substantially, and it is not uncommon for an "object
hierarchy" so-constructed to be 10 levels deep. ...that of course
brings with it its own challenges, but I'm mostly interested in how
"real" C coders view unnamed member variables and their use as
demonstrated above.

thanks for any insight,
-tom!
hi, u can use them like this

struct BaseObject {
int aMember2; /*just change to another name */
int anotherMember2;
};

struct GameObject
{
struct BaseObject;
int yetAnotherMember;

/*this can be defined anywhere but for convinience u can write here */
#define aMember BaseObject.aMember2
#define anotherMember BaseObject.anotherMember2
};

Now u can easily make use of these in any function:

void fn(GameObject* g)
{
g->aMember = 4;
g->anotherMember = 6;
g->yetAnotherMember = 839;
}


i think u got ur Solution now...

Jun 23 '06 #3

P: n/a
Tom Plunket wrote:
The project I'm currently on makes heavy use of unnamed
structures to represent an "object hierarchy" of a sort.

E.g.

struct BaseObject
{
int aMember;
int anotherMember;
// etc.
};

struct GameObject
{
struct BaseObject;
int yetAnotherMember;
// etc.
}; <snip> My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?"


The question we can definitively answer in comp.lang.c is "Is this
legal in C?" to which the answer is no, it invokes undefined
behaviour.

Google the archives for unnamed struct members for previous
discussions.

--
Peter

Jun 23 '06 #4

P: n/a
Tom Plunket posted:

struct GameObject
{
struct BaseObject;

int yetAnotherMember;
// etc.
};

That simply looks like a forward declaration.

Is this the syntax C uses to achieve inheritance? i.e. the C++ equivalent
of:
struct GameObject : BaseObject {

int yet_another_member;
};
Jun 23 '06 #5

P: n/a
Peter Nilsson wrote:
struct GameObject
{
struct BaseObject;
int yetAnotherMember;
// etc.
}; My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?"
The question we can definitively answer in comp.lang.c is "Is this
legal in C?" to which the answer is no, it invokes undefined
behaviour.


Huh, ok. That may be why I've never seen it before. It most
definitely doesn't compile in any of the C++ compilers I've used, but
there are three C compilers in play here at this time, and they're all
happy with this sort of structure. (MSVC.NET's, gcc 2.9something, and
snc from SN Systems.)
Google the archives for unnamed struct members for previous
discussions.


Thanks. Pretty much all I got were rants against typedefs and a
discussion about COBOL. ;) Alas, that it's "undefined" is enough
info for me. I suppose this "extension," then, is to normalize the
behavior of structs and unions in this case, as unnamed unions are
explicitly allowed by the standard, no? If unnamed unions are defined
and structs not, well, then I'm curious as to why, but this may not be
the forum for that answer.
-tom!
Jun 23 '06 #6

P: n/a
L7 wrote:
Although it is similar, it may be different enough for what you want:

#define COMMON_MEMBERS \
const char * name; \
struct info_t info; \
int type \


That is the most horrifying thing I have ever seen, and if one of my
programmers wrote that, I would fire her immediately.

:)
-tom!
Jun 23 '06 #7

P: n/a
Frederick Gotham wrote:
struct GameObject
{
struct BaseObject;

int yetAnotherMember;
// etc.
};

That simply looks like a forward declaration.

Is this the syntax C uses to achieve inheritance? i.e. the C++ equivalent
of:

struct GameObject : BaseObject {

int yet_another_member;
};


Yep.

Indeed, the code in question often does the following in header files:

typedef struct BaseObject BaseObject;

struct GameObject
{
#ifdef __c_plus_plus // or whatever it is
BaseObject BaseObject;
#else
BaseObject;
#endif

// ...
};

I'm not saying that I support this method of development (quite the
contrary, indeed), but I was looking more for "acceptability" in C
circles. As it appears that this is undefined behavior, I have all of
the answer I need to justify a "stop doing this now" command to the
team. ;) Some defend this as making the code "OO", but I'm sure that
many would agree that "pulling an object's names into another object's
namespace is not the definition of object-oriented." :)
-tom!
Jun 23 '06 #8

P: n/a
Tom Plunket <ga*****@fancy.org> writes:
Peter Nilsson wrote:
struct GameObject
{
struct BaseObject;
int yetAnotherMember;
// etc.
}; My question, finally, is, "is this sort of thing frequently used by
'real' C programmers?"
The question we can definitively answer in comp.lang.c is "Is this
legal in C?" to which the answer is no, it invokes undefined
behaviour.


It's undefined behavior, not a constraint violation?

[...] Thanks. Pretty much all I got were rants against typedefs and a
discussion about COBOL. ;) Alas, that it's "undefined" is enough
info for me. I suppose this "extension," then, is to normalize the
behavior of structs and unions in this case, as unnamed unions are
explicitly allowed by the standard, no? If unnamed unions are defined
and structs not, well, then I'm curious as to why, but this may not be
the forum for that answer.


No, unnamed unions are not allowed either, if I understand the term
correctly.

Given this:

struct inner_struct {
int a;
int b;
};

union inner_union {
int c;
int d;
};

struct outer {
struct inner_struct;
union inner_union;
};

both members of "struct outer" are invalid. gcc says:

tmp.c:12: warning: declaration does not declare anything
tmp.c:13: warning: declaration does not declare anything

With "ansi -pedantic", it says:

tmp.c:12: warning: ISO C doesn't support unnamed structs/unions
tmp.c:12: warning: declaration does not declare anything
tmp.c:13: warning: ISO C doesn't support unnamed structs/unions
tmp.c:13: warning: declaration does not declare anything
tmp.c:14: warning: struct has no members

--
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.
Jun 23 '06 #9

P: n/a
Keith Thompson wrote:
No, unnamed unions are not allowed either, if I understand the term
correctly.

Given this:

struct inner_struct {
int a;
int b;
};

union inner_union {
int c;
int d;
};

struct outer {
struct inner_struct;
union inner_union;
};

both members of "struct outer" are invalid. gcc says:

tmp.c:12: warning: declaration does not declare anything
tmp.c:13: warning: declaration does not declare anything


Huh, weird. ...because the code definitely compiles and operates "as
expected" in GCC here. Maybe it's a very old version of GCC. I
remember reading about unnamed union members in some GCC documentation
many years ago. Very interesting indeed, though.

The original text that I read allowed something along these lines:

struct Foo
{
union { int i; float f; };
double d;
};

void Fn()
{
Foo f;

f.i = 6;
}

....and I just assumed that what I was seeing here was along the same
lines, because it works identically; the "unnamed thing"'s members get
pulled into the containing struct's namespace.

Alas, I see clearly now that my initial revulsion was justified. :)
-tom!
Jun 23 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.