Thread: practical c programming - oreilly problem ?

  1. #1
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30

    practical c programming - oreilly problem ?

    example 11-2:
    page 177:
    the question:

    the HIGH_SPEED flag works, but the DIRECT_CONNECT flag does not. Why?

    I could see when i was typing it that you cant shift by more than 7 bits, and quite rightly expected the program to output:

    High speed set

    But for some reason i get:

    guyattc2-practical_c3-> high
    High speed set
    Direct connect set

    Can anyone tell me if ive copied it wrong or if there is an error. id like to know why my program works (bet thats a new one )

    Code:
    #include <stdio.h>
    
    const int HIGH_SPEED = (1<<7); /* modem is running fast */
    
    /* we are using a hardwired connection */
    const int DIRECT_CONNECT = (1<<8);
    
    char flags = 0; /* start with nothing */
    
    int main()
    {
    
      flags |= HIGH_SPEED; /* we are running fast */
      flags |= DIRECT_CONNECT; /*beacuse we are wired together */
    
      if((flags & HIGH_SPEED) != 0)
      {
    
        printf("High speed set\n");
      }
    
      if((flags & DIRECT_CONNECT) != 0)
      {
    
        printf("Direct connect set\n");
      }
    
      return(0);
    }
    Any help much appreciated, thanks.

    --CHriS

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > char flags = 0; /* start with nothing */
    Try making this an int
    One of your flags doesn't fit in a char, so it's lost

  3. #3
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30
    well i tried changing it to an int but there was no change. the whole point of this exercise (and chapter) was to explain bit operations. this was my understanding of the exercise when i was typing it up

    Code:
    const int HIGH_SPEED = (1<<7); /* modem is running fast */
    will mean HIGH_SPEED is set to 128 (10000000) as the 1 is shifted 7 bits to the left and all the bits coming from the right will all be 0's.

    Code:
    /* we are using a hardwired connection */
    const int DIRECT_CONNECT = (1<<8);
    will mean DIRECT_CONNECT is supposed to be set to 0 (00000000) as the one is shifted more than the 7 allowed and all the 0's fill in from the right. for some reason after checking using printf's it seems to set DIRECT_CONNECT to 256, so if char is 8-bits its somehow ... NOT! any way to make char make it equal 0 ???

    this comes from my original question: is there an erratum in the book, or is it me or the comps im using OR even the C compiler being to clever!?

    Anyway further help appreciated...

    --CHriS

  4. #4
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30
    ive just confused myself

    right so:

    DIRECT_CONNECT is an int and is set to (1<<8) which is 256.

    so when it is bitwise or'd with char flag we get:
    (1)00000000 DIRECT_CONNECT
    |= 00000000 flags
    -------------------
    00000000 and therefore false and therefore 0.

    so when it approaches the following code it should not execute the if statement!

    Code:
      if((flags & DIRECT_CONNECT) != 0)
      {
        
        printf("Direct connect set\n");
      }
    im trying to unconfuse myself here. anyone actually KNOW whats going on here? Hehe

    --CHriS
    Last edited by goosematt; 12-07-2004 at 08:10 AM.

  5. #5
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30
    ok, so outwardly thinking here. im going way out of my expertise

    if i made flags an int:

    100000000 DIRECT_CONNECT
    000000000 flags
    ---------------- |=
    100000000 and therefore 1 and therefore true ??

    --CHriS

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    When dealing with bit operations, you should be using unsigned types. I think you may be running into integer promotion and sign extension issues.
    Quote Originally Posted by goosematt
    is there an erratum in the book
    I haven't looked for this item yet, but a quick Google for "practical c programming errata" turned up this.
    Last edited by Dave_Sinkula; 12-07-2004 at 09:44 AM. Reason: Added quote and errata link.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Code:
      flags |= HIGH_SPEED; /* we are running fast */
      flags |= DIRECT_CONNECT; /*beacuse we are wired together */
    You're setting both bits...so both if() statements succeed. Another way to write the above code would be:
    Code:
      flags |= HIGH_SPEED | DIRECT_CONNECT;
    If you understand what you're doing, you're not learning anything.

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by itsme86
    Code:
      flags |= HIGH_SPEED; /* we are running fast */
      flags |= DIRECT_CONNECT; /*beacuse we are wired together */
    You're setting both bits...so both if() statements succeed.
    How about this, then?
    Code:
    #include <stdio.h>
    
    const int HIGH_SPEED     = (1U << 7);
    const int DIRECT_CONNECT = (1U << 8);
    
    char flags = 0;
    
    int main(void)
    {
       flags |= HIGH_SPEED;
       /*flags |= DIRECT_CONNECT;*/
    
       if ( (flags & HIGH_SPEED) != 0 )
       {
          puts("High speed set");
       }
    
       if ( (flags & DIRECT_CONNECT) != 0 )
       {
          puts("Direct connect set");
       }
    
       return 0;
    }
    
    /* my output
    High speed set
    Direct connect set
    */
    Last edited by Dave_Sinkula; 12-07-2004 at 10:32 AM. Reason: Trimmed quote.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30

    Unhappy

    hehe guys i think you might be missing the point?!...

    The program is *NOT* supposed to work. The whole point of this example in the book is that it was a question to show that you are not supposed to shift bits out of the range [76543210]...

    /* So the output *SHOULD* just be: */
    High speed set
    /* End of output */

    The "Direct connect set" should *NOT* be outputted! I dont want to FIX this problem, as i already know how! My point as in above post is that 1<<8 is the same as 0 and therefore should *NOT* execute the 2nd if!

    You see, im confusing everyone!

    --CHriS

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >char flags = 0; /* start with nothing */

    Per what Dave said with extending the sign bit, take your original code above and make flags unsigned and it should behave as expected:
    Code:
    unsigned char flags = 0; /* start with nothing */
    And for the same reason HIGH_SPEED and DIRECT_CONNECT should really be unsigned too.
    Last edited by swoopy; 12-07-2004 at 10:54 AM.

  11. #11
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30
    Quote Originally Posted by Dave_Sinkula
    >hehe guys i think you might be missing the point?!...

    And I think you missed my explanation.
    ahh sure. im back at home. was working on this at uni. but yeah i can see all your points now. hopefully it should all be good. although matey, you said your output was both... or did you mean that?! (sorry ive had a long day... its hard being a student hehe)

    --CHriS
    Last edited by goosematt; 12-07-2004 at 10:42 AM.

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    [For continuity, I deleted my post when I saw swoopy's reply, but apparently it was already quoted.]

    >you said your output was both... or did you mean that?!

    Yup.

    Setting the sign bit (aka HIGH_SPEED flag here) and sign-extending in the promotion to int for the comparison to DIRECT_CONNECT causes it to appear as if the DIRECT_CONNECT flag is set. The commented-out line in which it appears that the DIRECT_CONNECT flag is being set wasn't actually setting the bit, however.

    Another way to mess with this is to change HIGH_SPEED to (1 << 6) and leave that commented-out line in.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    * S T U D E N T *
    Join Date
    Oct 2003
    Posts
    30

    Talking

    Quote Originally Posted by Dave_Sinkula
    [For continuity, I deleted my post when I saw swoopy's reply, but apparently it was already quoted.]

    >you said your output was both... or did you mean that?!
    look at my first post. maybe i didnt explain it fully (i suffer from this disease)

    the exercise/question in the book should show that the output will ONLY be HIGH_SPEED and NOT both!

    In your quote, yes i did say that my output was both, which is therefore an error as i should only have HIGH_SPEED!

    (hmm little bits of repetition)

    also when i mentioned about the erratum, i wasnt stating whether there was one (i know about that link to oreilly and have already tried to check) but if there is not one then obviously i must submit one! (it would be my 3rd, the book is riddled with errara! )

    --CHriS

  14. #14
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I believe that setting a bit that's beyond the limit for a data type has undefined results per the standard. Therefore, setting that bit in this program shouldn't cause surprise when you see these results. It shouldn't surprise you if it begins a game of Frogger on your computer either.

    Unless I'm wrong about it being undefined
    If you understand what you're doing, you're not learning anything.

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by itsme86
    I believe that setting a bit that's beyond the limit for a data type has undefined results per the standard. Therefore, setting that bit in this program shouldn't cause surprise when you see these results. It shouldn't surprise you if it begins a game of Frogger on your computer either.

    Unless I'm wrong about it being undefined
    You can't cast an int to a char?
    6.3.1.3 Signed and unsigned integers
    1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
    2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)
    3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM