Regarding Left shift operator in embedded processor

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Respected Experts,

                     Iam RaviKumar.N, Iam using Intel-386EX embedded
processor for one of my application also Iam using a cross compiler
for the execution of my code. I have a query regarding left shift
operator.

              Consider the following variables:
               1) unsigned char a = 2;
               2) unsigned char b = 3;
               3) unsigned short c;

   Consider the following expression:

       c = (unsigned short)(( a << 8) | b);

  My query is:
             "Is it valid to shift a byte value by an 8-bit".

  I got this expression compiled,but Iam not sure about the results I
got.
  Please let me know about this.

  With Regards
   Ravi Kumar.N

Re: Regarding Left shift operator in embedded processor
On 12 Jan 2005 06:37:00 -0800, ravikumar.n@sunlux-india.com (Ravi

Quoted text here. Click to load it

consider this:

unsigned char a, b;
unsigned short c;

a = 1;
b = a << 8;
c = a << 8;

printf("b=%d, c=%d\n", b, c);

theoretically we should get the answer:
b=0, c=0

however... we get:
b=0, c25%6

we shoud get 0 in both cases because a << 8 should always give us 0
(zero) - that's assuming we were doing 8-bits (byte or char)
arithmetics - however - I guess the compiler (I know nothing about
compilers) is using something else than char (byte) arguments as it's
"temporary storage" - and that's the source of the problem...

but hey - maybe somebody else have a better explanation...

Re: Regarding Left shift operator in embedded processor

Quoted text here. Click to load it

ANSI Standard C promotes 8-bit chars to short integers for all
computations.  So a << 8 has a result of type unsigned short (or
possibly short) -- it doesn't get truncated until you stuff it back into
a character.

--

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
On Wed, 12 Jan 2005 16:08:52 -0800, Tim Wescott

Quoted text here. Click to load it

No, you are completely wrong.  Standard C requires that any type
shorted than an int gets promoted to either signed or unsigned int in
expressions.  Not short int, plain old ordinary int.  If the OP is
using a 16-bit compiler, short int and int happen to have the same
representation.  On the other hand, if he is using a 32-bit compiler,
that unsigned char is promoted to a full 32 bit signed int before the
shift operation happens.

--
Jack Klein
Home: http://JK-Technology.Com
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor

Quoted text here. Click to load it
I'd argue about the "totally" part, but not the nature of my mistake --
having been reminded by another poster on this I have already slapped my
forehead and said "doh!".

--

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it
... snip ...
Quoted text here. Click to load it

No, the promotion is into an integer.

--
Chuck F ( snipped-for-privacy@yahoo.com) ( snipped-for-privacy@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
On Wed, 12 Jan 2005 16:08:52 -0800, Tim Wescott

Quoted text here. Click to load it

well... I was right about one thing... I wrote: I know nothing about
compilers ;-)

but then - I "sensed" the problem correctly and for my own wellbeing I
know how to protect myself (and my code) against problems like that
;-) but it's good to know such things "for sure"...

Re: Regarding Left shift operator in embedded processor

Quoted text here. Click to load it

The C standard specifies how implicit type coercion will operate, but it is
best not to rely on standards compliance.  Instead write your assignment as:

c = ( ( unsigned short ) a <<  8 ) | ( unsigned short ) b;

That way you are telling the compiler what you want to happen.



Re: Regarding Left shift operator in embedded processor
in comp.arch.embedded:

Quoted text here. Click to load it

Makes absolutely no difference.  The casts to unsigned short serve no
purpose, and have no effect.  Most likely the compiler will optimize
them away.

Both 'a' and 'b' will be promoted to int for use as operands,
regardless of whether or not the compiler actually creates temporary
unsigned short values first.

No operations in C take operands of any rank less than int or unsigned
int.  Anything of lesser rank is always promoted.

Quoted text here. Click to load it

You may be telling the compiler what you want to happen, but if it
actually does so it is not a conforming C compiler.

--
Jack Klein
Home: http://JK-Technology.Com
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
ravikumar.n@sunlux-india.com says...
Quoted text here. Click to load it
This might be better directed to one of the C language news groups but
here goes.

Because of C's implicit promotion a and b are first promoted to int.  You
then left shift an int sized quantity (32 bits on a 386SX? or 16?), then
or that with another int sized quantity.  That result is then cast to an
unsigned short and (if the sizeof(unsigned short) is smaller than  
sizeof(int)) truncated.  Therefore you don't shift an 8-bit value.

The compiler is free to translate that into a sequence involving only 8
bit values provided it gets the same result as the above.

Robert

Re: Regarding Left shift operator in embedded processor



Quoted text here. Click to load it

bits in an int is a compiler value, not a CPU.
A 16 bit CPU could have a compiler with 32 ints.  OR old 16 bit compilers are
still 16 bits on a 32 bit CPU



Re: Regarding Left shift operator in embedded processor
On 12 Jan 2005 06:37:00 -0800, ravikumar.n@sunlux-india.com (Ravi

Quoted text here. Click to load it

Yes it is valid.  What happens is that "a" gets promoted from unsigned
char to int before it is shifted, so "a<<8" has the value 0x200.  "b"
is also promoted to unsigned int and or-ed with "a<<8".  The result is
0x203.


-Robert Scott
 Ypsilanti, Michigan
(Reply through this forum, not by direct e-mail to me, as automatic reply
address is fake.)

Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it

That's what the standard says will happen.  ISTR that there are
some compilers for 8-bit architectures that can generate code
that operates on un-promoted 8-bit integer types.

The OP would be better off putting in typecasts to tell the
compiler (and just as importantly the human reader) explicitly
what is supposed to happen:

  c = ((unsigned short)a << 8) | (unsigned short)b;

Since we're on an "explicit is better" topic, I prefer the
following [assuming that the OP wants a 16 bit result]:

  c = ((uint16_t a) << 8) | (uint16_t)b;

--
Grant Edwards                   grante             Yow!  Thank god!!... It's
                                  at               HENNY YOUNGMAN!!
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
comp.arch.embedded:

Quoted text here. Click to load it

Yes, some 8-bit compilers provide a non-standard extension of this
type.  But then the result would be undefined, because in C shifts
less than 0 or greater than equal to the width of the shifted type are
undefined.  Valid values for shifting an 8 bit type would be 0 to 7
inclusive.

Quoted text here. Click to load it

If the compiler operates in standard conforming mode, these casts
would be almost always useless, and cannot have any effect at all with
the particular values given here.

Even if the compiler did not optimize them away, the lvalue "(unsigned
short)a" will still be promoted to signed or unsigned int before the
actual shift is performed.  Same thing with the temporary value
"(unsigned short)b".

The only possible difference this could make would be on
implementations where short and int have the same range and
implementation, as would be the case for a 16-bit compiler for the
386EX.  In that case, the casting of 'a' and 'b' to unsigned short
would cause them to be promoted to unsigned int, rather than signed
int, before the shift and bitwise or.  On a 32-bit compiler for the
386EX (16-bit short, 32-bit int), 'a' and 'b' still end up as signed
ints because unsigned short promotes to signed int.

Quoted text here. Click to load it

Again, meaningless if int is wider than short, even with the misplaced
')' fixed, because those 16 bit temporaries will still get promoted to
signed 32-bit ints in a 32-bit implementation.

--
Jack Klein
Home: http://JK-Technology.Com
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it

Maybe.  The cast is useless, and should be omitted (as should most
casts) because it serves only to hide errors here.

The first thing that is done with 'a' is to extend it to an int in
order to operate on it.  The shift on that is legitimate, provided
it never becomes negative.  This requires that 'a' not have a high
order bit set, which is so in your example, but not in general.

The correct place for a cast is on 'a', to avoid the conversion to
int.

    c = ((unsigned)a << 8) | b;

You should always be very clear as to the purpose of any casts.

--
Chuck F ( snipped-for-privacy@yahoo.com) ( snipped-for-privacy@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it
I didn't think a cast from unsigned to a larger signed type would sign
extend.  Am I remembering incorrectly?

Robert

Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it

Please leave a blank line between the quotes and your reply, so we
can detect it.

Nothing to do with it here.  If a has a high order bit, the last of
the 8 shifts moves that into the sign position of an integer
(assumed 16 bits, which is all that the standard guarantees).  At
that point it is something (beyond the range of integer), and
behavior is no longer standardized.  Remember a left shift means
multiply by 2.

--
Chuck F ( snipped-for-privacy@yahoo.com) ( snipped-for-privacy@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
We've slightly trimmed the long signature. Click to see the full one.
Re: Regarding Left shift operator in embedded processor
Quoted text here. Click to load it

Oops, I guess I've gotten used to the colour distinctions in my current
newsreader.

Quoted text here. Click to load it

Ah, sign of the end result not the intermediate cast, different issue all
together.  (Forest remember than damn forest!)

Robert

Re: Regarding Left shift operator in embedded processor
You are correct. There is no sign to extend.


Re: Regarding Left shift operator in embedded processor

Quoted text here. Click to load it

Not for the vast majority of meanings the word "valid" in that
sentence could have, no.

On the typical platform, shifting a byte left by 8 yields a constant
zero --- if that was what you wanted, you could just have spelled out
that zero.

The correct way of doing what you wanted would be (with some extraneous
parentheses

    (((unsigned short) a) <<8) | b

I.e. turn a into a 2-byte value *before* you shift.

--
Hans-Bernhard Broeker ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Site Timeline