avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] mass stupidity with registers and longs


From: David Brown
Subject: Re: [avr-gcc-list] mass stupidity with registers and longs
Date: Fri, 14 Jan 2005 09:59:46 +0100

> On Friday 14 Jan 2005 6:18 am, Russell Shaw wrote:
> > Curtis Maloney wrote:
> > > I give up.  I've been trying to shift 4 chars into an unsigned
> > > long, but can't stop GCC 3.4.1 (what's shipped with the latest
> > > WinAVR) from sign extending values, let alone producing sane code.
> > >
> > > I've tried -Os, -O2, -O3, with and without -fnew-ra... the asm
> > > varies, but is generaly crap.
> > >
> > > now, if I have:
> > >     extern char a[4];
> > >     unsigned long ul;
> > >
> > >     ul = ( (unsigned)a[0] << 8 ) | (unsigned)a[1];
> > >
> > > why would it be sign extending a[0] and a[1] when they're cast to
> > > unsigneds?
> >
> > a[] is sign extended and the resulting integer interpreted as
> > unsigned.
>
> So what happens if you catch the type cast before it has to dereference
> a byte into an int? :-
>
>       extern char a[4];
>       unsigned long ul;
>
>       ul = ( ((unsigned char*)a)[0] << 8) | ((unsigned char*)a)[1];
>

Any use of plain "char" when you want to store a byte is bad coding - always
explictly use "signed char" or "unsigned char" (or typedefs like uint8).

If the original char was interpreted as signed, then casting to "unsigned"
will sign-extend it as you said.  However, your new code is failing to cast
it to 16-bit, so the shift by 8 will be done as 8-bit (actually, if I
understand the C standard correctly, the unsigned char will be cast to a
signed int, shifted, then cast back to an unsigned char !).  Try:

    ul = ( ((unsigned int) (unsigned char) a[0]) << 8U ) | ( (unsigned char
a[1]) );

Note the 8U to make 8 unsigned - by nature, literal integers are ints, and
the signedness could be coming from there.

The code produced is still not optimal (with my slightly out of date
compiler), but it's correct (i.e., no sign extensions).







reply via email to

[Prev in Thread] Current Thread [Next in Thread]