[comp.lang.c] struct/union/pointer query

ron@motmpl.UUCP (Ron Widell) (07/12/89)

My apologies if the previous posting went out, I tried to cancel it.

In trying to understand how to define, declare and use structures, unions
and pointers to same, I hacked up the following piece of strange code.
Now, I know it's ugly, but I thought that it was legal, yet I can't get
any (SGS, Sun, TurboC, MSC) compiler to take it unless I define BURP before
trying to compile. As I interpret K&R, 1e (page 120 in particular); I
think it should be legal, so why won't any of the compilers I've tried
accept it? Could I be wrong and the whole world be right :-)?

#include <stdio.h>

main()
{
	union {
		unsigned short foo;
#ifdef BURP
		struct burp {
#else
		struct {
#endif
			unsigned char fuz;
			unsigned char bar;
			} baz, *sptr;
	} glorp, *uptr;
#ifdef BURP
	struct burp  baz, *sptr;
#endif

	uptr = &glorp;
	sptr = &glorp.baz;
	uptr->foo = (unsigned short)0x4142;
	(void)putchar((char)sptr->fuz);
	(void)putchar('\n');
	(void)putchar((char)sptr->bar);
	(void)putchar('\n');
	return 0;
}
 Here's the output from lint:

junk.c
==============
(22)  sptr undefined
warning: illegal combination of pointer and integer:
    (22)  operator =
warning: struct/union or struct/union pointer required
    (24)  	    (26)  	

and here's the output (stderr) from SGS cc:

"junk.c", line 22: sptr undefined
"junk.c", line 22: warning: illegal pointer/integer combination, op =
"junk.c", line 24: warning: struct/union or struct/union pointer required
"junk.c", line 24: warning: struct/union or struct/union pointer required
"junk.c", line 26: warning: struct/union or struct/union pointer required
"junk.c", line 26: warning: struct/union or struct/union pointer required

Well, at least they agree :-).

BTW #1- I know that the *code* is bogus and very nonportable, and probably
works only by accident. It's there *only* to give lint and cc something to
munch on. I'm only interested in the legality of the union{..struct{..};};
definition/declaration.

BTW #2- What I *think* I'm defining is a union with three members: 1) an
unsigned short (on the target machine it's an int). 2) a structure of 2
unsigned chars. 3) a pointer to a structure of 2 unsigned chars.

Please respond via e-mail, I will summarize. Flame as required.

Regards,
-- 
Ron Widell, Field Applications Eng.	|UUCP: {...}mcdchg!motmpl!ron
Motorola Semiconductor Products, Inc.,	|Voice:(612)941-6800
9600 W. 76th St., Suite G		| I'm from Silicon Tundra,
Eden Prairie, Mn. 55344 -3718		| what could I know?

chris@mimsy.UUCP (Chris Torek) (07/18/89)

In article <1298@motmpl.UUCP> ron@motmpl.UUCP (Ron Widell) writes:
>Please respond via e-mail, I will summarize.

Good suggestion, but I will ignore it.  Anyway:

>... As I interpret K&R, 1e (page 120 in particular); I think [the
>following code, with #ifdef's edited away] should be legal, so why
>won't any of the compilers I've tried accept it?

>int main() {
>	union {
>		unsigned short foo;
>		struct {
>			unsigned char fuz;
>			unsigned char bar;
>			} baz, *sptr;
>	} glorp, *uptr;
>
>	uptr = &glorp;
>	sptr = &glorp.baz;
>	uptr->foo = (unsigned short)0x4142;

The best way to understand what has been declared above is to `unwind'
it.  This requires adding tags to any structure or union declarations
that do not already have them.  Here, the inner `struct' (containing
`fuz' and `bar') has no tag, so add one.  At the same time, move the
declaration out:

	struct ss {
		unsigned char fuz;
		unsigned char bar;
	};

Likewise, the union has no tag, so add one:

	union uu {
		unsigned short foo;
		struct ss baz, *sptr;
	};

Next, go through all the struct and union declarations and expand
type names for all members.  Here only the union has any commas:

	union uu {
		unsigned short foo;
		struct ss baz;
		struct ss *sptr;
	};

Now that all structures and unions are fully named, add the
main() function and its local variables.  What we now have is this:

	struct ss {
		unsigned char fuz;
		unsigned char bar;
	};

	union uu {
		unsigned short foo;
		struct ss baz;
		struct ss *sptr;
	};

	main()
	{
		union uu glorp, *uptr;

		uptr = &glorp;
-->		sptr = &glorp.baz;
		uptr->foo = (unsigned short)0x4142;

		[the rest is missing, unnecessary]

The line marked with the arrow (-->) is where things go wrong.  It
should be obvious at this point that main() has only two local
variables, one (`glorp') of type `union uu' and one (`uptr') of type
`pointer to union uu'.  The local variable `sptr' simply does not
exist.  (glorp contains a field called sptr, however.)

>... I'm only interested in the legality of the union{..struct{..};};
>definition/declaration.  What I *think* I'm defining is a union with
>three members: 1) an unsigned short ... . 2) a structure of 2 unsigned
>chars. 3) a pointer to a structure of 2 unsigned chars.

That is indeed what you defined.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris