Thread: Bit shift

  1. #1
    Registered User nenpa8lo's Avatar
    Join Date
    Jan 2008
    Posts
    42

    Bit shift

    Hi,

    Code:
    long unsigned int ShiftedBit = 0;
    
    ShiftedBit = 1 << 15;
    
    printf("%ld", ShiftedBit);
    Gives me a value of -32768. Code is written on 16 bit machine so unsigned int is 16bit and long unsigned bit is 32bit. How/why the value is negative?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Because 1 and 15 are not long, so 1 << 15 is a 16-bit integer, which is then converted to long. Make it 1L << 15 and it will work like you expect [or 1L << 15L].

    Of course, if you want to print an unsigned long, you should use %lu, not %ld. But you would get a huge number without the above changes to make the 1 and 15 long.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User nenpa8lo's Avatar
    Join Date
    Jan 2008
    Posts
    42
    Works now. Legend

  4. #4
    Registered User nenpa8lo's Avatar
    Join Date
    Jan 2008
    Posts
    42
    I've found that 1 << 31 gives 'long' (-2147483648) instead of 'unsigned long'. Is that correct?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by nenpa8lo View Post
    I've found that 1 << 31 gives 'long' (-2147483648) instead of 'unsigned long'. Is that correct?
    The result of unsigned or signed results are the same binary values - the only difference is how the value is interpreted by the display functions [and in comparisons]. In this case, did you actually notice my comment on using %lu rather than %ld when printing unsigned numbers? I think you are still using %ld, rather than %lu.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User nenpa8lo's Avatar
    Join Date
    Jan 2008
    Posts
    42
    The result of unsigned or signed results are the same binary values - the only difference is how the value is interpreted by the display functions [and in comparisons]
    so what's the real value of ShiftedBit?

    Bit representation is:

    Code:
    0x00008000 => 0000 0000 0000 0000 1000 0000 0000 0000
    So if I compare this then
    Code:
    unsigned long int OtherBit = 1;
    unsigned long int ShiftedBit = 0;
    
    ShiftedBit = 1 << 15;
    
    if (ShiftedBit > OtherBit)
        putchar('T');
    else
        putchar('F');
    Questions:
    1.In this instance OtherBit is greater than ShiftedBit, as ShiftedBit represents int value of -32768?
    2.Is the ShiftedBit implicitly casted to int?

    My compiler doesn't support %ul

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by nenpa8lo View Post
    so what's the real value of ShiftedBit?

    Bit representation is:

    Code:
    0x00008000 => 0000 0000 0000 0000 1000 0000 0000 0000
    So if I compare this then
    Code:
    unsigned long int OtherBit = 1;
    unsigned long int ShiftedBit = 0;
    
    ShiftedBit = 1 << 15;
    
    if (ShiftedBit > OtherBit)
        putchar('T');
    else
        putchar('F');
    Questions:
    1.In this instance OtherBit is greater than ShiftedBit, as ShiftedBit represents int value of -32768?
    That's wrong - like the next question, I'd like to know what compiler that is, since it sounds like the compiler is actually comparing signed when it should compare unsigned. [

    2.Is the ShiftedBit implicitly casted to int?

    My compiler doesn't support %ul
    %lu, you mean? What compiler is that? I'm not aware of ANY (as in, Turbo C++ that is 15+ years old supports it, as did the Compilers I used on Atari ST around 20 years ago) compiler that doesn't, but there's a first for everything.

    I recreated your test-case on my machine, using a short to temporarily hold the 1 << 15 value, and it creates a value that is 4 billion, which is greater than otherbit ("T" is output).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User nenpa8lo's Avatar
    Join Date
    Jan 2008
    Posts
    42
    Compiler is IAR for Embedded systems.

    From the manual:
    Code:
    The printf and sprintf functions use a common formatter called
    _formatted_write. The ANSI standard version of _formatted_write
    is very large, and provides facilities not required in many applications.
    To reduce the memory consumption the following two alternative
    smaller versions are also provided in the standard C library:
    -e_small_write
    -e_medium_write
    I use -e_small_write=_formatted_write (medium doesnt work either).

    Yes, I tried %lu - my 'typo'

    But, I've checked an assembly file (generated by the copiler if required), and look what I've found:
    Code:
    unsigned long int BShift;
    --C--
    BShift = 1 << 15;
    BShift = 1L << 15;
    
    --asm--
    mov.l   #-32768,er6
    mov.l   #32768,er0
    It looks like the compiler has precalculated values for 'constant' shifts and puts a value into register instead of making shift (wonder if that's for speed as this would take less cycles than shifting).

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sure, I expect the compiler to resolve constant expressions like that [for speed - since there is no point in calculating a value if it is calculated from constants].

    And yes, of course, if you use an embedded compiler that supplies a non-ANSI library, then you can expect to have non-standard behaviour.

    I still think it's a bug in the compiler that it compares two unsigned long incorrectly, whatever the origin of the values. I suggest you contact IAR about that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. 32 bit to 64 bit Ubuntu
    By Akkernight in forum Tech Board
    Replies: 15
    Last Post: 11-17-2008, 03:14 AM
  2. Replies: 7
    Last Post: 12-10-2004, 08:18 AM
  3. bit patterns of negtive numbers?
    By chunlee in forum C Programming
    Replies: 4
    Last Post: 11-08-2004, 08:20 AM
  4. Array of boolean
    By DMaxJ in forum C++ Programming
    Replies: 11
    Last Post: 10-25-2001, 11:45 PM