On Wed, 27 Nov 2013 11:31:26 EST erik quanstrom <[email protected]> 
wrote:
> On Wed Nov 27 11:04:46 EST 2013, [email protected] wrote:
> 
> > Whilst porting some code from the net I came across
> > the attached, rather obscure, code.
> > 
> > run as:
> > 
> >     larch% 8c -D 'STATIC=static' t.c && 8l t.8 && 8.out
> >     78780000
> >     larch% 8c -D 'STATIC=' t.c && 8l t.8 && 8.out
> >     0
> > 
> > I think it is tickling a bug in 8c, though
> > I may be just showing my lack of knowledge of
> > the C standard...
> > 
> > anyone any thoughts?
> 
> this code is not correct.  it breaks the anti-aliasing rules.  the
> compiler is allowed to assume that tmp is not modified.
> recently had trouble with floating point in stdio for the same
> reasons.

I think this is a compiler bug.  What happens when you
declare a union but still do, for example,

        (((uchar*)&tmp.i)[0] = ((uchar*)mem)[3]

etc.? I bet it works.

> to work around this, use a union, or better yet getle(buf, 3)
> (or be as the case may be),
> 
> since there's not enough context to sort out if the original is
> supposed to be big or little endian, here's a union version:
> 
> - erik
> ------
> #include <u.h>
> #include <libc.h>
> 
> static uint
> getdword_n(void *vmem, int n)
> {
>       uchar *mem;
>       union {
>               uint    i;
>               uchar   u[sizeof(uint)];
>       } tmp;
> 
>       mem = vmem;
>       tmp.i = 0;
>       switch (n){
>       case 3:
>               tmp.u[1] = mem[2];
>       case 2:
>               tmp.u[2] = mem[1];
>       case 1:
>               tmp.u[3] = mem[0];
>       }
>       return tmp.i;
> }
> 
> void
> main(void)
> {
>       uint x;
> 
>       char buf[] = "xxxx";
> 
>       x = getdword_n(buf, 2);
>       print("%x\n", x);
> }
> 

Reply via email to