bitshift operator problem

Discussion in 'C Programming' started by Serve Laurijssen, Sep 5, 2008.

  1. 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?
     
    Serve Laurijssen, Sep 5, 2008
    #1
    1. Advertising

  2. "Eric Sosman" <> schreef in bericht
    news:...
    > Serve Laurijssen wrote:
    >> 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

    > 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.
     
    Serve Laurijssen, Sep 5, 2008
    #2
    1. Advertising

  3. Serve Laurijssen

    Flash Gordon Guest

    Serve Laurijssen wrote, On 05/09/08 14:56:
    >
    > "Eric Sosman" <> schreef in bericht
    > news:...
    >> Serve Laurijssen wrote:
    >>> 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
    >
    >> 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
     
    Flash Gordon, Sep 5, 2008
    #3
  4. "Serve Laurijssen" <> writes:
    > "Eric Sosman" <> schreef in bericht
    > news:...
    >> Serve Laurijssen wrote:
    >>> 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) <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"
     
    Keith Thompson, Sep 5, 2008
    #4
  5. "Flash Gordon" <> schreef in bericht
    news:-gordon.me.uk...
    > 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.


    > 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
     
    Serve Laurijssen, Sep 5, 2008
    #5
  6. Serve Laurijssen

    Willem Guest

    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
     
    Willem, Sep 5, 2008
    #6
  7. Serve Laurijssen

    Ali Karaali Guest

    Alright ;

    What happenes if a sign integer shifts left or right?

    I mean what is the situation of sign bit.
     
    Ali Karaali, Sep 6, 2008
    #7
  8. Serve Laurijssen

    Ali Karaali Guest

    >  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?
     
    Ali Karaali, Sep 6, 2008
    #8
  9. Serve Laurijssen

    Ali Karaali Guest

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


    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, Sep 6, 2008
    #9
  10. Serve Laurijssen

    Ali Karaali Guest

    > Eric Sosman
    >


    What about;

    signed char i = 1;

    i << 7;
     
    Ali Karaali, Sep 6, 2008
    #10
  11. Serve Laurijssen

    CBFalconer Guest

    Ali Karaali wrote: **** and removed attributions - bad ****
    >
    >> 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, Sep 6, 2008
    #11
  12. Serve Laurijssen

    CBFalconer Guest

    Ali Karaali wrote:
    >

    .... total lack of useful quotes ...
    >
    > What about;
    >
    > signed char i = 1;


    works !!!
    >
    > i << 7;


    works !!! result is discarded.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
     
    CBFalconer, Sep 6, 2008
    #12
  13. CBFalconer <> writes:

    > Ali Karaali wrote: **** and removed attributions - bad ****
    >>
    >>> 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, Sep 6, 2008
    #13
  14. Ali Karaali <> writes:

    >> Eric Sosman
    >>

    >
    > 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.
     
    Ben Bacarisse, Sep 6, 2008
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ryan
    Replies:
    4
    Views:
    2,982
    Rusty Wright
    Feb 14, 2005
  2. bollod
    Replies:
    12
    Views:
    515
    Richard Heathfield
    Dec 27, 2003
  3. Replies:
    8
    Views:
    333
    Larry I Smith
    Feb 10, 2006
  4. Replies:
    6
    Views:
    384
    Grant Edwards
    May 24, 2007
  5. Bill Cunningham

    bitshift

    Bill Cunningham, Nov 8, 2011, in forum: C Programming
    Replies:
    1
    Views:
    297
    Lew Pitcher
    Nov 9, 2011
Loading...

Share This Page