Thread: Signed/Unsigned char issues

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    20

    Signed/Unsigned char issues

    Code:
    signed char n = -94;
    unsigned char p;
    
    p = (n >>3) | (n << (8-3));
    
    putc(p);
    Signed char n is -94, which is 10100010
    After doing a bit rotate, it should be 01010100, which is then put into Unsigned char p.

    I am expecting the putc to be printing out 'T', which is 01010100 (decimal 84). However, it is printing an o with a carat above it, which the debug is showing as decimal 244, or 11110100.

    What am I missing here?

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    What is 10100010 shifted left five times?
    What is 10100010 shifted right three times?


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    20
    Quote Originally Posted by quzah View Post
    What is 10100010 shifted left five times?
    What is 10100010 shifted right three times?


    Quzah.
    They are 01000000 and 00010100. Then they are OR'd together, which should produce 01010100, then that should be moved into p

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Are you sure they aren't 01000000 and 11110100?

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> What am I missing here?

    Remember: the result of a shift is an *int*. So what happens is the signed char is first converted to an int, and because of sign extension the most significant bits of the int are filled with ones (because the value is negative). When the value is shifted right all of these ones are of course shifted into the least significant byte. At any rate, you just need to cast the value to an unsigned type before shifting to get the correct results.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If it's signed, then it depends on how they feel like implementing it. It could be zeros, it could be the left most bit's value, depending on the direction you're shifting anyway. I find it easiest to just write a function to spit out what the bits look like, if what I'm shifting doesn't look like what I think it should.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jun 2008
    Posts
    20
    Ah! Thanks guys. That would make sense. If the char is signed, and it's a negative number, then a bit shift converts the char to an int, and fills up the most significant byte with 1's, so that when shifting right, those 1's are pulled in.

    Makes sense now, but I thought I was going crazy for a bit there. Thanks.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Not sure what the OP means by "bit rotate" which is slightly different from shifting.
    Given "10100010" pattern, a bit rotate left puts the MSB into the LSB.
    Remaining bits are shifted left resulting in "01000101" bit pattern.

  9. #9
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote Originally Posted by NewbGuy View Post
    Ah! Thanks guys. That would make sense. If the char is signed, and it's a negative number, then a bit shift converts the char to an int, and fills up the most significant byte with 1's, so that when shifting right, those 1's are pulled in.

    Makes sense now, but I thought I was going crazy for a bit there. Thanks.
    No, not quite. On my system, if I shift:
    Code:
    10000000000000000000000000000000
    ...which is a negative, to the right, I get something like:
    Code:
    11111100000000000000000000000000
    1s are shifted in. Note what quzah said, since:

    Quote Originally Posted by C89
    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.
    (Emphasis mine.)
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  10. #10
    Registered User BlackOps's Avatar
    Join Date
    Jul 2009
    Location
    AZERBAIJAN
    Posts
    78
    well, just for interest i tried to cast n to the unsigned int, but it stil gives the value of 244..

    Code:
    signed char n = -94;
    unsigned char p;
    
    
    
    p =   ((unsigned int)n >>3) | (n << (8-3)) ;
    
    printf("%d", p);
    p is still 244... so how to make it 84?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You only cast one side.
    The other side is still doing signed integer shifting.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by BlackOps
    just for interest i tried to cast n to the unsigned int, but it stil gives the value of 244..
    Cast to unsigned char. When you cast to unsigned int, you get a non-negative integer equal to UINT_MAX + 1 - 94.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    If you know x86 assembly, this is the difference between SHR (shift right) and SAR (shift arithmetic right). If the number is treated as signed, then the sign bit is duplicated as the value shifts right.

    It's almost never correct to apply shifts to signed quantities. Shifting implies that you are processing a quantity in a bitwise fashion. But the bits within a signed quantity have special meanings. If you are manipulating bits you should always be using unsigned types.

    (I suppose you could be trying to use the trick where you shift right instead of dividing by a power of two. Don't use that trick. The compile IS smart enough to do that for you. If not, get a better compiler)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  14. #14
    Registered User BlackOps's Avatar
    Join Date
    Jul 2009
    Location
    AZERBAIJAN
    Posts
    78
    yes! casting to unsigned char helped, ok =)

  15. #15
    Registered User
    Join Date
    Jun 2008
    Posts
    20
    Quote Originally Posted by laserlight View Post
    Cast to unsigned char. When you cast to unsigned int, you get a non-negative integer equal to UINT_MAX + 1 - 94.
    This is what I did and it worked. Thanks all. Learned a lot with this thread.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sorting Linked Lists
    By DKING89 in forum C Programming
    Replies: 6
    Last Post: 04-09-2008, 07:36 AM
  2. Conversion Char To Char * Problem
    By ltanusaputra in forum Windows Programming
    Replies: 3
    Last Post: 03-01-2008, 02:06 PM
  3. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  4. newbie needs help with code
    By compudude86 in forum C Programming
    Replies: 6
    Last Post: 07-23-2006, 08:54 PM
  5. String sorthing, file opening and saving.
    By j0hnb in forum C Programming
    Replies: 9
    Last Post: 01-23-2003, 01:18 AM