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

Union nested in structure.

P: n/a
I created a C file say struct.c with the following structure
declarations in the same file

struct A
{
union key
{
int i;
float f;
}k1;
};
struct B
{
union key
{
int i;
float f;
}k2;
};
When I compiled this code using
gcc -c struct.c

I got a error

"redefinition of `union key'" at the definition of "union key" in
struct B.
Is it not that the scope "union key" defined in struct A is limited to
struct A? From the behaviour it looks like that nested unions have
global scope.

Can anyone provide me the reason for such behavior?

When i made the file as struct.cpp it compiled without any problem.
Similar is the behaviour if I nest a struct inside a struct..

Nov 14 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a

ta*****@gmail.com wrote:
I created a C file say struct.c with the following structure
declarations in the same file

struct A
{
union key
{
int i;
float f;
}k1;
};
struct B
{
union key
{
int i;
float f;
}k2;
};
When I compiled this code using
gcc -c struct.c

I got a error

"redefinition of `union key'" at the definition of "union key" in
struct B.
Is it not that the scope "union key" defined in struct A is limited to
struct A? From the behaviour it looks like that nested unions have
global scope.

Can anyone provide me the reason for such behavior?

When i made the file as struct.cpp it compiled without any problem.
Congratulations: You have just found one of the differences between
the two languages C and C++.
C has _one_ namespace for _all_ structure, union and enumeration tags.
No scope. Effectively, you can write:
struct A
{
union key
{
int i;
float f;
}k1;
};

struct B
{
union key k2;
};
or
union key
{
int i;
float f;
};

struct A
{
union key k1;
};

struct B
{
union key k2;
};
Cheers
Michael

Similar is the behaviour if I nest a struct inside a struct..


Exactly as the language standard demands it.
Cheers
Michael
--
E-Mail: Mine is a gmx dot de address.

Nov 14 '05 #2

P: n/a
But why does C standard demand such a behaviour? C is very particular
about scope. Why is that scope rules are not followed in case of
structures, unions and enums?

Nov 14 '05 #3

P: n/a
Tapeesh wrote:

But why does C standard demand such a behaviour? C is very particular
about scope. Why is that scope rules are not followed in case of
structures, unions and enums?


Your question makes no sense. What behaviour? In usenet so called
previous articles are often not available at the receivers station,
so each article should stand on its own. That is why we include
attributions and quotations. Even with googles broken beta system
you can do it, see my sig below.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #4

P: n/a
"Tapeesh" <ta*****@gmail.com> writes:
But why does C standard demand such a behaviour? C is very particular
about scope. Why is that scope rules are not followed in case of
structures, unions and enums?


The scope rules are followed. It just happens that the rules are
different for struct, union, and enum tags.

As for why it was originally defined that way, I suppose it was just
easier. This probably goes back at least 30 years. You can certainly
argue that limiting the scope of a tag makes more sense (and
apparently Stroustrup felt strongly enough about it to change the rule
for C++), but the C rules rarely cause problem in practice. (Your
code is one of the rare cases.) It can't be changed now without
potentially breaking existing code.

(BTW, this is a good argument against always compiling your C code
with a C++ compiler; it can cause you to miss this kind of error.)

--
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.
Nov 14 '05 #5

P: n/a

In article <11**********************@f14g2000cwb.googlegroups .com>, "Tapeesh" <ta*****@gmail.com> writes:

I see Chuck Falconer has already posted explaining why you should
(properly) quote text you are replying to, and how to do so correctly
with the braindead Google Groups interface. I won't repeat those
instructions, but I urge you to take them to heart.
But why does C standard demand such a behaviour?
Because that's how the committee thought it should work, and not
specifying the tag scope rules would have been a Bad Thing.

(And, IIRC, the single global-scope tag namespace existed in pre-
standard C as well, so they're preserving existing practice. What
did change was the separation of members into their own scoped
namespace. Or was it that members had their own namespace, but it
had global scope? Or was there only a single namespace for tags,
members, and ordinary identifiers? I no longer have a pre-standard
K&R to consult.)
C is very particular about scope.
With good reason. That does not mean, however, that the scoping
rules are or should be the same for all namespaces.
Why is that scope rules are not followed in case of
structures, unions and enums?


They are. They're just different for the tag namespaces.

The only reason to put a tag on a struct (or union) is to make it a
distinct type. You can leave the tags off structs (or unions) if
they don't need to be treated as distinct types. Often that's the
case when you're defining one struct inside another; otherwise, why
not define the inner one separately, first, to show that it may be
used on its own?

--
Michael Wojcik mi************@microfocus.com

It does basically make you look fat and naked - but you see all this stuff.
-- Susan Hallowell, TSA Security Lab Director, on "backscatter" scanners
Nov 14 '05 #6

P: n/a
>
(BTW, this is a good argument against always compiling your C code
with a C++ compiler; it can cause you to miss this kind of error.)


Well considering 99.9998% of C/C++ compilers will compile aprogram.c
as a 'C' language file, I don't see this problem popping up often, unless
of course they are using command-line parameters (and you'd have a hard
time finding them with gcc [joking]).

Nathaniel L. Walker
Nov 14 '05 #7

P: n/a
"Nathaniel L. Walker" <NatLWalker@no_email.org> writes:
(BTW, this is a good argument against always compiling your C code
with a C++ compiler; it can cause you to miss this kind of error.)


Well considering 99.9998% of C/C++ compilers will compile aprogram.c
as a 'C' language file, I don't see this problem popping up often,
unless of course they are using command-line parameters (and you'd
have a hard time finding them with gcc [joking]).


This problem pops up all the time here. A lot of people name their C
source files with a ".cpp" suffix. (Note also that some OSs don't
distinguish between "aprogram.c" and "aprogram.C"; I'm not sure how
compilers on those systems behave.)

--
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.
Nov 14 '05 #8

P: n/a
Nathaniel L. Walker wrote:
(BTW, this is a good argument against always compiling your C code
with a C++ compiler; it can cause you to miss this kind of error.)
Well considering 99.9998% of C/C++ compilers will compile aprogram.c


GNU cc and c++ aren't in that list. See example below.
as a 'C' language file, I don't see this problem popping up often, unless
of course they are using command-line parameters (and you'd have a hard
time finding them with gcc [joking]).

Nathaniel L. Walker


/* trouble.c
(5 green apples + 4 red apples) != 9 red apples.
C != C++.
*/
#include <stdio.h>

enum truth_value {lies, truth};

int
main (void)
{
const enum truth_value statistics = lies;

char *delete = "telling the C++ compiler to throw up.";

if (statistics == lies)
printf ("you know what I mean. :)\n");

puts (delete);

return 0;
}

----
Compiling with a C compiler (one of the most popular ones):

% gcc -pedantic -Wall -std=c89 -o statistics statistics.c
or
% gcc -pedantic -Wall -std=c99 -o statistics statistics.c
% ./statistics
you know what I mean. :)
telling the C++ compiler to throw up.

Compiling with a C++ compiler (one of the most popular ones, again):

% g++ -pedantic -Wall -o statistics statistics.c
statistics.c: In function `int main()':
statistics.c:10: error: expected primary-expression before "char"
statistics.c:10: error: expected `;' before "char"
statistics.c:15: error: expected primary-expression before ')' token

Ooh, my C++ compiler doesn't recognize the .c extension that is so
very clearly present right there.

Bottom line: C != C++. Use a C compiler to compile C code and
use a C++ compiler to compile C++ code. :)

Regards,
Jonathan.

--
Email: "jonathan [period] burd [commercial-at] gmail [period] com" sans-WSP

"I usually swear at C++, but so far it has never sworn back."
- Ben "Noir"
Nov 14 '05 #9

P: n/a
Jonathan Burd wrote:
Nathaniel L. Walker wrote:

<snip>

/* trouble.c
Should be statistics.c.
Regards,
Jonathan.

--
Email: "jonathan [period] burd [commercial-at] gmail [period] com" sans-WSP

"I usually swear at C++, but so far it has never sworn back."
- Ben "Noir"
Nov 14 '05 #10

P: n/a
On 9 Feb 2005 20:36:47 GMT, mw*****@newsguy.com (Michael Wojcik)
wrote:
<snip>
Because that's how the committee thought it should work, and not
specifying the tag scope rules would have been a Bad Thing.

(And, IIRC, the single global-scope tag namespace existed in pre-
standard C as well, so they're preserving existing practice. What
did change was the separation of members into their own scoped
namespace. Or was it that members had their own namespace, but it
had global scope? Or was there only a single namespace for tags,
members, and ordinary identifiers? I no longer have a pre-standard
K&R to consult.)

*Very* early C had one namespace for (names of) members of all structs
-- or at least all structs at (what we now call) file scope, I don't
recall if there were struct definitions within a function/block at all
-- and you could apply member names "of" (from) any struct as members
of any (other) struct, with often wrong results. This is why the API
structs that survive from early Unix like tm (tm_year, tm_mon etc.)
and <not standard C> stat (st_mode, st_mtime etc.) have the struct
encoded in the member names to ensure they don't conflict. I'm pretty
sure that even then members were isolated from ordinary identifiers
and tags; and that members became per-struct even before K&R1 much
less the standard, though I also no longer have a 1ed to check.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.