passing a union's field to a function

M

Mikhail Teterin

Hello!

The sample program below is compiled fine by gcc (with -Wall), but rejected
by Sun's SUNWspro compiler (version 6 update 2).

The point of contention is, whether a value for one of the union's types can
be passed to a function directly -- without creating a separate variable of
the union type and assigning the appropriate field of it.

Is gcc being too liberal, or is this behavior simply part of a newer
C-standard, which Sun's old compiler is not supporting? Thanks!

-mi
 
R

Richard Heathfield

Mikhail Teterin said:
Hello!

The sample program below is compiled fine by gcc (with -Wall), but
rejected by Sun's SUNWspro compiler (version 6 update 2).

What sample program?
The point of contention is, whether a value for one of the union's types
can be passed to a function directly -- without creating a separate
variable of the union type and assigning the appropriate field of it.

The value of the most recently assigned union member object can be passed to
a function directly. There is no need to copy it out.
Is gcc being too liberal, or is this behavior simply part of a newer
C-standard, which Sun's old compiler is not supporting? Thanks!

Who knows? I don't see your code.
 
M

Mikhail Teterin

Richard said:
What sample program?

Your news-reader must be doing something nasty with attachments.

The program was attached to the original posting. Here it is inline.

-mi

#include <stdio.h>

typedef union {
ššššššššintššššši;
ššššššššvoidšššš*p;
ššššššššstruct {
ššššššššššššššššintššššši;
ššššššššššššššššintšššššj;
šššššššš}šššššššs;
} testunion;

static void
testfunc(testunion u)
{
ššššššššprintf("i: %d\np: %p\n", u.i, u.p);
}

int
main()
{
šššššššštestfunc((testunion)3);
šššššššštestfunc((testunion)NULL);
ššššššššreturn 0;
}
 
R

Richard Heathfield

Mikhail Teterin said:
Your news-reader must be doing something nasty with attachments.

Attachments don't happen in comp.lang.c - it's a text-only newsgroup.
#include <stdio.h>

typedef union {
int i;
void *p;
struct {
int i;
int j;
} s;
} testunion;

static void
testfunc(testunion u)
{
printf("i: %d\np: %p\n", u.i, u.p);

Either you put in an int, in which case it's okay to print the int but not
the void *, or you put in a void *, in which case it's okay to print the
void * but not the int.
}

int
main()
{
testfunc((testunion)3);

That's not a valid conversion.
testfunc((testunion)NULL);

Neither is that.
 
M

Mikhail Teterin

Richard said:
Attachments don't happen in comp.lang.c - it's a text-only newsgroup.

Mine was a text-only attachement. And I can see it on my news-server...
Mikhail Teterin said:

That's not a valid conversion.

But gcc has no problem with it, and my question was: "why?" Is gcc too lax,
or is it aware of a newer C-standard that neither then Sun's compiler nor
you are aware of?

If a function expects a union, one of whose fields is `int':

typedef union {
int i;
void *p;
struct {
int i;
int j;
} s;
} testunion;

then passing an integer argument (with or without casting) is quite
unambigious -- gcc's treatment seems perfectly reasonable to me...

-mi
 
K

Keith Thompson

Mikhail Teterin said:
The sample program below is compiled fine by gcc (with -Wall), but rejected
by Sun's SUNWspro compiler (version 6 update 2).

The point of contention is, whether a value for one of the union's types can
be passed to a function directly -- without creating a separate variable of
the union type and assigning the appropriate field of it.

Is gcc being too liberal, or is this behavior simply part of a newer
C-standard, which Sun's old compiler is not supporting? Thanks!

#include <stdio.h>

typedef union {
int i;
void *p;
struct {
int i;
int j;
} s;
} testunion;

static void
testfunc(testunion u)
{
printf("i: %d\np: %p\n", u.i, u.p);
}

int
main()
{
testfunc((testunion)3);
testfunc((testunion)NULL);
return 0;
}

Your program appeared in my newsreader as an attachment. Please don't
post attachments here; just copy your source code into the text of
your article.

You can't cast to a union type in either C90 or C99. gcc apparently
provides this as an extension. This is mentioned in the "C
Extensions" section of the gcc documentation. That documentation will
also tell you about the "-ansi -pedantic" or, if you prefer, "-std=c99
-pedantic" options, which would have warned you about this.
 
I

Ian Collins

Mikhail said:
Richard Heathfield wrote:




Mine was a text-only attachement. And I can see it on my news-server...
Doesn't matter, text-only newsgroups don't forward attachments.
But gcc has no problem with it, and my question was: "why?" Is gcc too lax,
or is it aware of a newer C-standard that neither then Sun's compiler nor
you are aware of?
In default mode, gcc will compile just about anything remotely like C.

gcc -Wall -pedantic -ansi /tmp/x.c
/tmp/x.c: In function `main':
/tmp/x.c:21: warning: ISO C forbids casts to union type
/tmp/x.c:22: warning: ISO C forbids casts to union type

Compile with an appropriate warning level, you'll learn more that way.
 
K

Keith Thompson

Mikhail Teterin said:
Your news-reader must be doing something nasty with attachments.

The program was attached to the original posting. Here it is inline.

Ugh, that's worse. In my newsreader, it shows up with a bunch of
non-printable '\232' characters.

I don't know how they got there, but try to use only spaces for
indentation. Copy and paste plain text if you can.
 
M

Mikhail Teterin

Ian said:
In default mode, gcc will compile just about anything remotely like C.

I'm compiled with -Wall, not default, although I don't use -pedantic.
gcc -Wall -pedantic -ansi /tmp/x.c
/tmp/x.c: In function `main':
/tmp/x.c:21: warning: ISO C forbids casts to union type
/tmp/x.c:22: warning: ISO C forbids casts to union type

Compile with an appropriate warning level, you'll learn more that way.

With -Wall, but without -pedantic, the code still compiles cleanly and works
as expected:

% gcc -Wall -o union union.c
% ./union
i: 3
p: 3
i: 0
p: 0

Adding "-pedantic" does, indeed, elicit warnings you quote. So, is there a
way to pass a value to a union-expecting function, without creating a union
and copying the values around, as in:

testunion t;

t.i = i;
testfunc(t);

Why can't I just do:

testfunc(i)

? Is there any kind of ambiguity here?

The reason, I'm so insistant is not only having to copy values around and
create (seemingly) useless local variables. It is also that Purify reports
such passing of unions as a UMR (Uninitialized Memory Read), because other
(longer) fields of the union remain unitilized (such as the s.j field in my
sample union) and putting them onto stack (for a function call)
means "reading" them...

Thanks,

-mi
 
M

Mikhail Teterin

Keith said:
Ugh, that's worse. In my newsreader, it shows up with a bunch of
non-printable '\232' characters.

I just saved it back to a file from the news-reader. The file is perfectly
clean, opens up fine in vi, and compiles...
I don't know how they got there, but try to use only spaces for
indentation. šCopy and paste plain text if you can.

BSD's style(9) mandates use of tabs for indentation :)

http://www.freebsd.org/cgi/man.cgi?query=style&sektion=9

Yours,

-mi
 
M

Mikhail Teterin

Keith said:
Your program appeared in my newsreader as an attachment. Please don't
post attachments here

Why? Is not a (text) attachement easier to deal with? None of the "---- cut
here ---" nuissance, just save into a file and compile...
You can't cast to a union type in either C90 or C99. gcc apparently
provides this as an extension. This is mentioned in the "C
Extensions" section of the gcc documentation. That documentation will
also tell you about the "-ansi -pedantic" or, if you prefer, "-std=c99
-pedantic" options, which would have warned you about this.

Thanks for the most useful answer... Any ideas on why this is not part of
the C-standard (yet?)? What's wrong with this extension -- what does it
break? Yours,

-mi
 
R

Robert Gamble

Mikhail said:
I just saved it back to a file from the news-reader. The file is perfectly
clean, opens up fine in vi, and compiles...

Well, your "inline" version looks like crap on Google Groups as well,
take a look for yourself if you'd like.
BSD's style(9) mandates use of tabs for indentation :)

http://www.freebsd.org/cgi/man.cgi?query=style&sektion=9

Perhaps you don't realize it but this is Usenet, not the BSD kernel.
Spaces are the recommended method of indentation here and for good
reason.

Robert Gamble
 
I

Ian Collins

Mikhail said:
Adding "-pedantic" does, indeed, elicit warnings you quote. So, is there a
way to pass a value to a union-expecting function, without creating a union
and copying the values around, as in:

testunion t;

t.i = i;
testfunc(t);

Why can't I just do:

testfunc(i)

? Is there any kind of ambiguity here?
Think of your union as an object. If you had written

typedef struct { int n; } X;

void testFn( X x ) {}

You wouldn't expect to be able to pass an int to testFn, same when the
parameter is a union.
The reason, I'm so insistant is not only having to copy values around and
create (seemingly) useless local variables.

Why worry? Let the compiler take care of optimising away local variables.
It is also that Purify reports
such passing of unions as a UMR (Uninitialized Memory Read), because other
(longer) fields of the union remain unitilized (such as the s.j field in my
sample union) and putting them onto stack (for a function call)
means "reading" them...
What else did you expect?

Using unions as function parameters is not a good idea in my opinion.
If you do, I'd recommend wrapping them in a simple struct with a member
used to indicate which member of the union is being passed:

typedef union {
int i;
void *p;
struct {
int i;
int j;
} s;
} testunion;


typedef struct {
enum { Int, Void, Struct} key;
testunion value;
} X;

static void testfunc( X* x ){}

int main(void)
{
X x;
x.key = Int;
x.value.i = 42;

testfunc( &x );

return 0;
}
 
I

Ian Collins

Mikhail said:
Keith Thompson wrote:




Why? Is not a (text) attachement easier to deal with? None of the "---- cut
here ---" nuissance, just save into a file and compile...
Some people use news readers that don't support attachments. On Usenet,
go for the lowest common denominator, plain text.
 
M

Mikhail Teterin

Ian said:
Some people use news readers that don't support attachments. On Usenet,
go for the lowest common denominator, plain text.

Come on -- that's not a valid argument. The attachements have appeared more
than 10 years ago and all news-readers (including text based ones) now
support them.

A text-only attachement is no different, really from a "--- cut here ---" --
look at the "body" of my original message to see, what I mean. It is not
encoded, and the reader is not expected to render any images. One could
telnet to port 119, speak NNTP to get the article and would *still* get the
posted textual attachment correctly...

-mi
 
M

Mikhail Teterin

Robert said:
Perhaps you don't realize it but this is Usenet, not the BSD kernel.
Spaces are the recommended method of indentation here and for good
reason.

The reason being?..

-mi
 
K

Keith Thompson

Mikhail Teterin said:
Why? Is not a (text) attachement easier to deal with? None of the "---- cut
here ---" nuissance, just save into a file and compile...

No, it isn't. At least one responder said his newsreader didn't even
show him the attachment. Each newsreader handles attachments in its
own way, and they're strongly discouraged in discussion groups.

The "--- cut here ---" stuff is easy enough to handle.
Thanks for the most useful answer... Any ideas on why this is not part of
the C-standard (yet?)? What's wrong with this extension -- what does it
break?

There are an unlimited number of things that could be added to the
standard. If they were all added, a copy of the standard would be too
heavy to lift. New features shouldn't be added to the core language
just for the sake of a minor convenience.
 
M

Mikhail Teterin

Ian said:
Think of your union as an object. If you had written

typedef struct { int n; } X;

void testFn( X x ) {}

You wouldn't expect to be able to pass an int to testFn, same when the
parameter is a union.

But I don't think of it as an object -- not in this case. It is just a way
to pass a different type of argument to the same function (without the mess
of varargs/stdargs).
Why worry? Let the compiler take care of optimising away local variables.

The code looks ugly -- with many extra lines. It also requires the caller to
know about the union's internals, when all it needs to know, is that it
passes a number.
What else did you expect?

Well, I expect Purify to tell me about *real* problems in the code... Having
been alerted to this by Purify, I tried to come up with a better
replacement for the alarm-triggering code...
Using unions as function parameters is not a good idea in my opinion.
If you do, I'd recommend wrapping them in a simple struct with a member
used to indicate which member of the union is being passed.

In my case the type is specified by an earlier argument (stripped away for
the sample program posted). Same thing, really.
X x;
x.key = Int;
x.value.i = 42;

testfunc( &x );

Right, that would work. But is not:

testfunc(Int, 42);

easier and neater? It also leaves no way for the callee to modify the
caller's variable, thus allowing better compiler optimizations...

By now I've learned from this thread, that I'm seeing a gcc-extension in
action. Why is such an extension not adopted by the C-standard remains my
question, though...

-mi
 
K

Keith Thompson

Mikhail Teterin said:
The reason being?..

tabs can be messed up or lost in transit. I have no idea how or why,
but it happens; someone posts this:

<TAB>{
<TAB><TAB>/* indented text */
<TAB>}

and it shows up like this:

{
/* indented text*/
}

If you're on a Unix-like system, you can filter your text through
"expand" before posting it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top