Aliasing question... 
Author Message
 Aliasing question...

Hello all.

I'm looking for somebody who can vet the standards available, and tell me
why the following piece of code is illegal:

union a_union {
        int i;
        double d;

Quote:
};

int f(void) {
        a_union t;
        int *ip;

        t.d = 3.0;
        ip = &t.i;

        return *ip;

Quote:
}

I can understand that code like the following may not necessarily work,
but the union above, I personally think should.  Non-working code:

int f(void) {
        double d = 3.0;
        int *ip = (int *)&d;

        return *ip;

Quote:
}

--Toby.
*----------------------------------------------------------------------------*

| Apt B, 7707-110 St. |-----------------------------| 100 Tradecenter Drive  |
| Edmonton, AB        | Unix Guru? Admin, Sys-Prgmr | Champaign, IL          |
|----------------------------------------------------------------------------|
|      %SYSTEM-F-ANARCHISM, The operating system has been overthrown         |
*----------------------------------------------------------------------------*
--



Sat, 09 Feb 2002 03:00:00 GMT  
 Aliasing question...

Quote:

> Hello all.

> I'm looking for somebody who can vet the standards available, and tell me
> why the following piece of code is illegal:

> union a_union {
>         int i;
>         double d;
> };

Remember that the above does not define a type a_union.  This would do
so:
    typedef union {
            int i;
            double d;
     } a_union;

This becomes important in

Quote:

> int f(void) {
>         a_union t;

Where you either need the typedef above or a declaration like
         union a_union t;

--

__________________________________________________________
Fight spam now!
Get your free anti-spam service: http://www.brightmail.com
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...


Quote:
>Hello all.

>I'm looking for somebody who can vet the standards available, and tell me
>why the following piece of code is illegal:

Are you asking for the rationale for why the standard made it undefined
behaviour, or are you asking if it is?

Apart from the licence to read and write storage as unsigned char,
writing memory as one type and reading it as another exhibits undefined
behaviour.  Remember that means that no requirements are placed on the
behaviour by the standard.  Of course it may work, an implementer may
even guarantee that it will 'work'.

As to why? Well you have already accepted the thesis with your second
example.  But if you need more clarification, remember that
sizeof(float) often does not equal sizeof(double)  and in addition the
only types that are required to have all bit patterns defined are the
char types.

Quote:

>union a_union {
>       int i;
>       double d;
>};

>int f(void) {
>       a_union t;
>       int *ip;

>       t.d = 3.0;
>       ip = &t.i;

>       return *ip;
>}

>I can understand that code like the following may not necessarily work,
>but the union above, I personally think should.  Non-working code:

>int f(void) {
>       double d = 3.0;
>       int *ip = (int *)&d;

>       return *ip;
>}

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...

Quote:

> Hello all.

> I'm looking for somebody who can vet the standards available, and tell me
> why the following piece of code is illegal:

> union a_union {
>         int i;
>         double d;
> };

> int f(void) {
>         a_union t;
>         int *ip;

>         t.d = 3.0;
>         ip = &t.i;

>         return *ip;
> }

> I can understand that code like the following may not necessarily work,
> but the union above, I personally think should.  Non-working code:

> int f(void) {
>         double d = 3.0;
>         int *ip = (int *)&d;

>         return *ip;
> }

I'm not sure that "illegal" is the right word.  Undefined is more like
it.

In many implementations, I would expect the two examples to have
identical
results, so are functionally equivalent.  My reasoning is that your
union
definition makes the members i and d occupy the same space in memory.
Apart from some compiler specific things like byte alignment, (and
ignoring
differences in [say] types of i and d) &t.i, &t.d, and &t will usually
return a pointer to the same address in memory.

Perhaps if you define what you mean by "work", someone may be able to
give
you a better approach.

Given that different systems have different representations of int and
double types, it is reasonable to expect results of both your examples
to be undefined.

-<Automagically included trailer>
Robert O'Dowd                       Ph    +61 (8) 8259 6546
MOD/DSTO                            Fax    +61 (8) 8259 5139
P.O. Box 1500                       Email:

Salisbury, South Australia, 5108

Disclaimer: Opinions above are mine and may be worth what you paid for
them
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...
Tobias Weingartner a crit dans le message ...

Quote:
>I'm looking for somebody who can vet the standards available, and tell me
>why the following piece of code is illegal:

>union a_union {
> int i;
> double d;
>};

>int f(void) {
> a_union t;
> int *ip;

> t.d = 3.0;
> ip = &t.i;

> return *ip;
>}

Your code is not compiling. The reason is that the way you declared a_union
needs to be used in conjunction with the 'union' keyword .

union a_union
{
   int i;
   double d;

Quote:
};

int main (void)
{
   union a_union t; /* 'union' has been added */

   return 0;

Quote:
}

An alternate way that I personnaly prefer because I am very lazy :

typedef union
{
   int i;
   double d;

Quote:
}a_union;

int main (void)
{
   a_union t;

   return 0;

Quote:
}

--
HS

--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...
This is a quick followup on my own question.  The question was one dealing
with optimizations, not necessarily the representations of floating-point
values in integers, nor the potential signals/etc that this might evoke.

Basically, the question was answered by a nice guy (names, I forget names!)
who mentioned that union should be looked at as "variant storage".  Not the
"overlay, in memory" that most of us old-hard-core systems programmers tend
to think when somebody says "union".

--Toby.

Quote:

> I'm looking for somebody who can vet the standards available, and tell me
> why the following piece of code is illegal:

> union a_union {
>    int i;
>    double d;
> };

[Rest Deleted]
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...

(Tobias Weingartner) wrote in comp.lang.c.moderated:

Quote:
> Hello all.

> I'm looking for somebody who can vet the standards available, and tell me
> why the following piece of code is illegal:

> union a_union {
>    int i;
>    double d;
> };

> int f(void) {
>    a_union t;
>    int *ip;

>    t.d = 3.0;
>    ip = &t.i;

>    return *ip;
> }

> I can understand that code like the following may not necessarily work,
> but the union above, I personally think should.  Non-working code:

> int f(void) {
>    double d = 3.0;
>    int *ip = (int *)&d;

>    return *ip;
> }

> --Toby.

Why do you think there is any difference between the two?  A pointer
to a union, or any member of a union, can be suitably cast to a
pointer to any other member of the union.  But you are doing the same
thing in both cases:  accessing an object using an lvalue of a
different type.

Accessing an object using an lvalue of a different type results in
undefined behavior unless the access is done using a character type.
Even then this might produce undefined behavior on some systems unless
the character type is an unsigned char, because signed char is allowed
to contain trap representations, as is specified in the C9X draft.

The fact that you are using a union does not change this.

Jack Klein
--
Home: http://home.att.net/~jackklein
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...

Quote:
Toby Weingartner writes:
> ... tell me why the following piece of code is illegal:

There is no such term as "illegal" in the standard.

Quote:
> union a_union {
>    int i;
>    double d;
> };

> int f(void) {
>    a_union t;

Syntax error: you have not defined any type named "a_union".  Either
the initial declaration should be changed to a typedef, or the above
line should read:

        union a_union t;

Reread questions 2.1 and 2.2 in the FAQ list.  Or in the current standard,
read sections 6.5.2.3 and 6.5.6.

Quote:
>    int *ip;

>    t.d = 3.0;
>    ip = &t.i;

>    return *ip;
> }

This part of the code is correct, but the behavior is implementation-
defined at best; as I said in another thread, see section 6.3.2.3.

Furthermore, if the implementation happens to have sizeof(int) >
sizeof(double), then the behavior is undefined.  Initially t has
indeterminate value (see section 6.5.7); assigning to t.d will not
affect the bytes of t.i that aren't part of t.d.  So the evaluation
of *ip in this case accesses bytes that are still indeterminate and
hence causes undefined behavior (see section 3.16).

Quote:
> I can understand that code like the following may not necessarily work,
> but the union above, I personally think should.  Non-working code:

> int f(void) {
>    double d = 3.0;
>    int *ip = (int *)&d;

>    return *ip;
> }

Indeed, this code contains an additional problem in that &d may not be
correctly aligned for conversion to int * and hence "the resulting
pointer might not be valid" (section 6.3.4), causing undefined behavior
when it's used.  This is not an issue for unions because section 6.5.2.1
guarantees that pointers to their members are interconvertible and hence
that the members are correctly aligned for such a conversion.

If the pointer is valid in this version of the code, then the behavior
is still implementation-defined and possibly undefined for the reasons
explained under the other version.
--
Mark Brader              |    "[This computation] assumed that everything
Toronto                  |     would work, a happy state of affairs found

My text in this article is in the public domain.
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...

Quote:

> I'm looking for somebody who can vet the standards available, and tell me
> why the following piece of code is illegal:

> union a_union {
>         int i;
>         double d;
> };

> int f(void) {
>         a_union t;

This won't compile because a_union is a union tag here, not a typedef.  Try
"union a_union t;".  Are you sure you're compiling in C mode, not C++?

Quote:
>         int *ip;

>         t.d = 3.0;
>         ip = &t.i;

>         return *ip;
> }

You are writing to one part of the union but reading from another, which isn't
legal unless they're the same type.  Once you do this, you're invoking
implementation-defined behavior.

Quote:
> I can understand that code like the following may not necessarily work,
> but the union above, I personally think should.  Non-working code:

> int f(void) {
>         double d = 3.0;
>         int *ip = (int *)&d;

>         return *ip;
> }

What do you mean by "non-working"-- what do you expect it to do?  Converting a
pointer-to-double to a pointer-to-int and then dereferencing is
implementation-defined, too.  It's not the same as converting an int to a
double, if that's what you're after.
--



Sun, 10 Feb 2002 03:00:00 GMT  
 Aliasing question...

Quote:


> > Hello all.

> > I'm looking for somebody who can vet the standards available, and tell me
> > why the following piece of code is illegal:

> > union a_union {
> >         int i;
> >         double d;
> > };

> > int f(void) {
> >         a_union t;
> >         int *ip;

> >         t.d = 3.0;
> >         ip = &t.i;

> >         return *ip;
> > }

> > I can understand that code like the following may not necessarily work,
> > but the union above, I personally think should.  Non-working code:

> > int f(void) {
> >         double d = 3.0;
> >         int *ip = (int *)&d;

> >         return *ip;
> > }

> I'm not sure that "illegal" is the right word.  Undefined is more like
> it.

> In many implementations, I would expect the two examples to have
> identical
> results, so are functionally equivalent.  My reasoning is that your
> union
> definition makes the members i and d occupy the same space in memory.
> Apart from some compiler specific things like byte alignment, (and
> ignoring
> differences in [say] types of i and d) &t.i, &t.d, and &t will usually
> return a pointer to the same address in memory.

In fact they will _always_ return a pointer to the same address.  The
standard guarantees it.  (But don't ask me where -- I just looked and
couldn't find it.  I'm certain it's there, though.  This was discussed
a few months ago.)

/peter
--



Mon, 11 Feb 2002 03:00:00 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. Aliasing through union, C++ vs. C

2. ANSI aliasing rules

3. Aliasing in ANSI C

4. Aliasing and character types

5. Sequence Points, Aliasing & Optimisation

6. difference between punning and aliasing

7. aliasing single quotes in macros

8. aliasing quotes in macros?

9. difference between punning and aliasing

10. aliasing

11. anti aliasing filter source

12. aliasing

 

 
Powered by phpBB® Forum Software