Connecting Tech Pros Worldwide Forums | Help | Site Map

bitshift operator problem

Serve Laurijssen
Guest
 
Posts: n/a
#1: Sep 5 '08
I've been working on an old 8-bit system and came across a problem with the
<< operator

This would always yield 0:

unsigned char i;
for (i = 0; i < 4; i++)
{
unsigned char idx = 1 << i;
....
}

while this worked as expected:

unsigned char i, mask = 1;
for (i = 0; i < 4; i++)
{
unsigned char idx = mask;
....
mask = mask << 1;
}

Is there something wrong with the first version considering that this is
code for an 8-bitter?


Eric Sosman
Guest
 
Posts: n/a
#2: Sep 5 '08

re: bitshift operator problem


Serve Laurijssen wrote:
Quote:
I've been working on an old 8-bit system and came across a problem with
the << operator
>
This would always yield 0:
>
unsigned char i;
for (i = 0; i < 4; i++)
{
unsigned char idx = 1 << i;
....
}
By "yield 0" do you mean that the value of idx was
always zero in "...."? That shouldn't be so: idx should
have been 1, 2, 4, 8 on the four loop iterations. How
did you discover that idx was zero (or have I not
understood your complaint)?
Quote:
while this worked as expected:
>
unsigned char i, mask = 1;
for (i = 0; i < 4; i++)
{
unsigned char idx = mask;
....
mask = mask << 1;
}
What were your expectations, and how did you verify
that they were met? In this loop, both idx and mask should
have the values 1, 2, 4, 8 during "...." in each iteration,
and mask should be 16 after the loop ends.
Quote:
Is there something wrong with the first version considering that this is
code for an 8-bitter?
First tell us more about your intentions, and about your
means of discovering what your code fragments are doing.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Serve Laurijssen
Guest
 
Posts: n/a
#3: Sep 5 '08

re: bitshift operator problem



"Eric Sosman" <esosman@ieee-dot-org.invalidschreef in bericht
news:McOdnWqfr-EYiFzVnZ2dnUVZ_g2dnZ2d@comcast.com...
Quote:
Serve Laurijssen wrote:
Quote:
>I've been working on an old 8-bit system and came across a problem with
>the << operator
>>
>This would always yield 0:
>>
>unsigned char i;
>for (i = 0; i < 4; i++)
>{
> unsigned char idx = 1 << i;
> ....
>}
>
By "yield 0" do you mean that the value of idx was
always zero in "...."? That shouldn't be so: idx should
have been 1, 2, 4, 8 on the four loop iterations. How
did you discover that idx was zero (or have I not
understood your complaint)?
That was what I meant yes. It was seen with a debugger. I'm guessing a
compiler bug then
Quote:
First tell us more about your intentions, and about your
means of discovering what your code fragments are doing.
a debugger. The bits were used to set a signal and after that read a signal
from a register to check if a button was pressed.

Flash Gordon
Guest
 
Posts: n/a
#4: Sep 5 '08

re: bitshift operator problem


Serve Laurijssen wrote, On 05/09/08 14:56:
Quote:
>
"Eric Sosman" <esosman@ieee-dot-org.invalidschreef in bericht
news:McOdnWqfr-EYiFzVnZ2dnUVZ_g2dnZ2d@comcast.com...
Quote:
>Serve Laurijssen wrote:
Quote:
>>I've been working on an old 8-bit system and came across a problem
>>with the << operator
>>>
>>This would always yield 0:
>>>
>>unsigned char i;
>>for (i = 0; i < 4; i++)
>>{
>> unsigned char idx = 1 << i;
>> ....
>>}
>>
> By "yield 0" do you mean that the value of idx was
>always zero in "...."? That shouldn't be so: idx should
>have been 1, 2, 4, 8 on the four loop iterations. How
>did you discover that idx was zero (or have I not
>understood your complaint)?
>
That was what I meant yes. It was seen with a debugger. I'm guessing a
compiler bug then
>
Quote:
> First tell us more about your intentions, and about your
>means of discovering what your code fragments are doing.
>
a debugger. The bits were used to set a signal and after that read a
signal from a register to check if a button was pressed.
Did you use the value of idx? I'm guessing possibly not, or possibly it
was only assigned to what C thought of as a variable but was actually
memory mapped HW. Check that you have used 'volatile' for the
declaration/definition of anything which is mapped to HW.

I've implemented scanning a hex keypad in SW before, strobing the fours
lines checking for whether any of the relevant 4 bits are set, and I'm
guessing this is what you are doing. I was doing it because I was
writing SW to test the keypad, normally I would just use a dedicated
chip to do it.
--
Flash Gordon
Keith Thompson
Guest
 
Posts: n/a
#5: Sep 5 '08

re: bitshift operator problem


"Serve Laurijssen" <zhu@woaini.comwrites:
Quote:
"Eric Sosman" <esosman@ieee-dot-org.invalidschreef in bericht
news:McOdnWqfr-EYiFzVnZ2dnUVZ_g2dnZ2d@comcast.com...
Quote:
>Serve Laurijssen wrote:
Quote:
>>I've been working on an old 8-bit system and came across a problem
>>with the << operator
>>>
>>This would always yield 0:
>>>
>>unsigned char i;
>>for (i = 0; i < 4; i++)
>>{
>> unsigned char idx = 1 << i;
>> ....
>>}
>>
> By "yield 0" do you mean that the value of idx was
>always zero in "...."? That shouldn't be so: idx should
>have been 1, 2, 4, 8 on the four loop iterations. How
>did you discover that idx was zero (or have I not
>understood your complaint)?
>
That was what I meant yes. It was seen with a debugger. I'm guessing a
compiler bug then
Or a debugger bug.

[...]

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Eric Sosman
Guest
 
Posts: n/a
#6: Sep 5 '08

re: bitshift operator problem


Serve Laurijssen wrote:
Quote:
>
"Eric Sosman" <esosman@ieee-dot-org.invalidschreef in bericht
news:McOdnWqfr-EYiFzVnZ2dnUVZ_g2dnZ2d@comcast.com...
Quote:
>Serve Laurijssen wrote:
Quote:
>>I've been working on an old 8-bit system and came across a problem
>>with the << operator
>>>
>>This would always yield 0:
>>>
>>unsigned char i;
>>for (i = 0; i < 4; i++)
>>{
>> unsigned char idx = 1 << i;
>> ....
>>}
>>
> By "yield 0" do you mean that the value of idx was
>always zero in "...."? That shouldn't be so: idx should
>have been 1, 2, 4, 8 on the four loop iterations. How
>did you discover that idx was zero (or have I not
>understood your complaint)?
>
That was what I meant yes. It was seen with a debugger. I'm guessing a
compiler bug then
Compilers certainly have bugs, but a bug as basic as this
would very likely have been detected and fixed long ago. It
seems to me more likely that you're looking in the wrong place.
Keep in mind that when you assign a value to idx, the compiler is
not obliged to store that value in idx' memory cell immediately.
It might, for example, hold the value in a CPU register until
several assignments have been made, and only store the last of
them. It might even eliminate all stores, if it can deduce
that they're not needed. Compilers are sly, devious beasts
at times.

From a C language perspective, all we can say is that
`idx = 1 << i;' is perfectly valid, and should yield a well-
defined result (for the types and values in your code). The
particulars of what your compiler does with the code and/or
how your debugger observes the result are specific to your
compiler and debugger. Another forum -- comp.arch.embedded,
maybe? -- might be of help with those matters.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Serve Laurijssen
Guest
 
Posts: n/a
#7: Sep 5 '08

re: bitshift operator problem



"Flash Gordon" <spam@flash-gordon.me.ukschreef in bericht
news:2ur7p5x7q4.ln2@news.flash-gordon.me.uk...
Quote:
Did you use the value of idx? I'm guessing possibly not, or possibly it
was only assigned to what C thought of as a variable but was actually
memory mapped HW. Check that you have used 'volatile' for the
declaration/definition of anything which is mapped to HW.
Ok thanks. I just wanted to know if (1<<i) was 100% correct from a C point
of view. The expression would be converted to int because of the 1 which
caused the problem. Using ints on this platform generates lots more (non
atomic) instructions and since it was called in an interrupt handler some
stuff could go wrong there. But anyway, ((unsigned char)1<<i) didnt work
either.

Quote:
I've implemented scanning a hex keypad in SW before, strobing the fours
lines checking for whether any of the relevant 4 bits are set, and I'm
guessing this is what you are doing. I was doing it because I was writing
SW to test the keypad, normally I would just use a dedicated chip to do
it.
it was just part of a test program

Willem
Guest
 
Posts: n/a
#8: Sep 5 '08

re: bitshift operator problem


Serve Laurijssen wrote:
) Ok thanks. I just wanted to know if (1<<i) was 100% correct from a C point
) of view. The expression would be converted to int because of the 1 which
) caused the problem. Using ints on this platform generates lots more (non
) atomic) instructions and since it was called in an interrupt handler some
) stuff could go wrong there. But anyway, ((unsigned char)1<<i) didnt work
) either.

Maybe you should check what the assembler instructions are that the
compiler generates.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Ali Karaali
Guest
 
Posts: n/a
#9: Sep 6 '08

re: bitshift operator problem


Alright ;

What happenes if a sign integer shifts left or right?

I mean what is the situation of sign bit.
pete
Guest
 
Posts: n/a
#10: Sep 6 '08

re: bitshift operator problem


Ali Karaali wrote:
Quote:
Alright ;
>
What happenes if a sign integer shifts left or right?
>
I mean what is the situation of sign bit.
N869
6.5.7 Bitwise shift operators

[#4] The result of E1 << E2 is E1 left-shifted E2 bit
positions; vacated bits are filled with zeros. If E1 has an
unsigned type, the value of the result is E1×2E2, reduced
modulo one more than the maximum value representable in the
result type. If E1 has a signed type and nonnegative value,
and E1×2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

[#5] The result of E1 > E2 is E1 right-shifted E2 bit
positions. If E1 has an unsigned type or if E1 has a signed
type and a nonnegative value, the value of the result is the
integral part of the quotient of E1 divided by the quantity,
2 raised to the power E2. If E1 has a signed type and a
negative value, the resulting value is implementation-
defined.

--
pete
Eric Sosman
Guest
 
Posts: n/a
#11: Sep 6 '08

re: bitshift operator problem


Ali Karaali wrote:

[... without quoting any context to make his message sensible.
For those just tuning in, the question was about `1 << i'.]
Quote:
Alright ;
>
What happenes if a sign integer shifts left or right?
>
I mean what is the situation of sign bit.
It's not clear whether you're asking about the signedness
of `i' or of `1' (which is obviously positive, but perhaps you
are asking about a more general left-hand operand).

If `i' is negative, the behavior is undefined. Note that
this is a weaker statement than "the result is undefined,"
because it does not even imply that there will be a result.
Similarly, the behavior is undefined if `i' is greater than
*or equal to* the number of value bits in the (promoted) left-
hand operand, or if `i' is large enough to cause any one-bit
of the l.h.o. to be shifted beyond the value-bit positions.

If `1' is negative (that is, if the left-hand operand, not
actually `1', is negative), the behavior is undefined.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Ali Karaali
Guest
 
Posts: n/a
#12: Sep 6 '08

re: bitshift operator problem


*If E1 has a signed type and nonnegative value,
Quote:
* * * * and E1×2E2 is representable in the result type, then that is
* * * * the resulting value; OTHERWISE, the behavior is undefined..

What is OTHERWISE?
Ali Karaali
Guest
 
Posts: n/a
#13: Sep 6 '08

re: bitshift operator problem


* * *If `1' is negative (that is, if the left-hand operand, not
Quote:
actually `1', is negative), the behavior is undefined.
>
--
Eric Sosman
esos...@ieee-dot-org.invalid
Actually I would like to know what is the result of?
Was it define?

int i = 1; // i is a signed integer
i << 2;
Ali Karaali
Guest
 
Posts: n/a
#14: Sep 6 '08

re: bitshift operator problem


Eric Sosman
Quote:
esos...@ieee-dot-org.invalid
What about;

signed char i = 1;

i << 7;

CBFalconer
Guest
 
Posts: n/a
#15: Sep 6 '08

re: bitshift operator problem


Ali Karaali wrote: **** and removed attributions - bad ****
Quote:
>
Quote:
>If E1 has a signed type and nonnegative value,
>and E1×2E2 is representable in the result type, then that is
>the resulting value; OTHERWISE, the behavior is undefined.
>
What is OTHERWISE?
If E1 has an unsigned type or negative value, or E1*2E2 is not
representablie in the result type. :-)

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
CBFalconer
Guest
 
Posts: n/a
#16: Sep 6 '08

re: bitshift operator problem


Ali Karaali wrote:
Quote:
>
.... total lack of useful quotes ...
Quote:
>
What about;
>
signed char i = 1;
works !!!
Quote:
>
i << 7;
works !!! result is discarded.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
pete
Guest
 
Posts: n/a
#17: Sep 6 '08

re: bitshift operator problem


CBFalconer wrote:
Quote:
Ali Karaali wrote: **** and removed attributions - bad ****
Quote:
Quote:
>>If E1 has a signed type and nonnegative value,
>>and E1×2E2 is representable in the result type, then that is
>>the resulting value; OTHERWISE, the behavior is undefined.
>What is OTHERWISE?
>
If E1 has an unsigned type or negative value, or E1*2E2 is not
representablie in the result type. :-)
>
Well, that's the meaning of the what he quoted,
but, he left out the previous sentence:
If E1 has an
unsigned type, the value of the result is E1×2E2, reduced
modulo one more than the maximum value representable in the
result type.
So, shifting an unsigned type is always defined.

What's also undefined, is if (E1) is signed
and (E1 << E2) excedes the max value for the type, for example:
(INT_MAX << 1)
is undefined.

--
pete
Eric Sosman
Guest
 
Posts: n/a
#18: Sep 6 '08

re: bitshift operator problem


Ali Karaali wrote:
Quote:
Quote:
>Eric Sosman
>esos...@ieee-dot-org.invalid
>
What about;
>
signed char i = 1;
>
i << 7;
No problem. First, the value of `i' is promoted to int.
Then the int is left-shifted seven places, giving the value 128.
Then the result is ignored.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Ben Bacarisse
Guest
 
Posts: n/a
#19: Sep 6 '08

re: bitshift operator problem


CBFalconer <cbfalconer@yahoo.comwrites:
Quote:
Ali Karaali wrote: **** and removed attributions - bad ****
Quote:
>>
Quote:
>>If E1 has a signed type and nonnegative value,
>>and E1×2E2 is representable in the result type, then that is
>>the resulting value; OTHERWISE, the behavior is undefined.
>>
>What is OTHERWISE?
>
If E1 has an unsigned type or negative value, or E1*2E2 is not
representablie in the result type. :-)
Not sure if the smiley is there just to say "yes, I know I got this
wrong, I am joking".

For the OP: (1) the odd E1x2E2 means E1 times 2 raised to the power E2
(the text version of the standard that CBFalconer uses looses the
formatting of powers). (2) The otherwise refers to those cases when
the result is not previously covered. You need to read the whole
thing, including the previous part:

3 The integer promotions are performed on each of the operands. The
type of the result is that of the promoted left operand. If the
value of the right operand is negative or is greater than or equal
to the width of the promoted left operand, the behavior is
undefined.

4 The result of E1 << E2 is E1 left-shifted E2 bit positions;
vacated bits are filled with zeros. If E1 has an unsigned type,
the value of the result is E1 x 2^E2 , reduced modulo one more
than the maximum value representable in the result type. If E1 has
a signed type and nonnegative value, and E1 x 2^E2 is
representable in the result type, then that is the resulting
value; otherwise, the behavior is undefined."

So E2 being too big or too small (negative) is covered by 3. In all
other cases E1 << E2 is well-defined if E1 is an unsigned type. The
otherwise refers to those cases when E1 is signed and the result can't
be represented in the promoted type. Thus, on most systems you will
come across,

1 << (sizeof(int) * CHAR_BIT - 1)

is undefined.

--
Ben.
Ben Bacarisse
Guest
 
Posts: n/a
#20: Sep 6 '08

re: bitshift operator problem


Ali Karaali <alicpp@gmail.comwrites:
Quote:
Quote:
>Eric Sosman
>esos...@ieee-dot-org.invalid
>
What about;
>
signed char i = 1;
>
i << 7;
This is fine (but daft sine the result is thrown away). The shift is
performed after promoting the operands and 1 << 7 is representable as
in int (the promoted type). See my other message to the full wording.

This, however,

i = i << 7;

is likely to be a problem because the integer result of the shift
(128) probably can't be converted back to a signed char. C99 says you
get implementation-defined behaviour or an implementation-defined
signal is raised.

--
Ben.
Closed Thread