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);
> }
>