Thread: c puzzle

  1. #1
    Registered User ralu.'s Avatar
    Join Date
    Feb 2009
    Location
    Bucharest, RO
    Posts
    32

    c puzzle

    For those who like to keep your mind sharp or for those who want to test their skills in programming here is an interesting C programming bug:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
      while(1) {
        fprintf(stdout, "out \t");
        fprintf(stderr, "err \t");
        sleep(1);
      }
        
      return 0;
    }
    This program will not print on the screen "out".. can you say why?
    I have stopped reading Stephen King novels. Now I just read C code instead.

  2. #2
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by ralu. View Post
    here is an interesting C programming bug:
    It's not a bug!

    standard out is buffered output, and that buffer is only flushed when:
    a) it's full
    b) you call fflush()
    c) you print a \n

    QuantumPete

    edit:
    Try this to illustrate:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
      int num = 5;
      while(num--) {
        fprintf(stdout, "out \t");
        fprintf(stderr, "err \t");
        sleep(1);
      }
      fprintf (stdout, "\n");  
      return 0;
    }
    Last edited by QuantumPete; 03-05-2009 at 03:39 AM. Reason: Added illustration program
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    And of course, it's all depending on the implementation of the C library. Sure, stderr is DEFINED as unbuffered, whilst stdout is buffered, but there is nothing saying that stdout has to have a buffer bigger than 1 character.

    --
    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.

  4. #4
    Registered User ralu.'s Avatar
    Join Date
    Feb 2009
    Location
    Bucharest, RO
    Posts
    32
    Here it is another interesting problem:

    Code:
    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
      int i;
      double num = 0.0;
    
      for(i = 0; i < 10; i++)
        num = num + 0.1;
    
      if(num == 1.0)
        printf("num == 1.0\n");
      else
        printf("num != 1.0\n");
    
      return 0;
    }
    I have stopped reading Stephen King novels. Now I just read C code instead.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It's not interesting, it's a known fact of 0.1 being one of many numbers that can't be stored PRECISELY in the standard binary floating point formats. It becomes 0.09999999999999999999999 when you translate it back to decimal (the number of nines depend on the length of the binary format, and the actual printout with lots of digits may show some "random" values at the end, depending how the bits at the end match up with the digits printed).

    Obviously, adding 0.09999999... together ten times leaves you with a number similar to 0.9999999... which is not precisely 1.0, so a comparison on a bit-level will see them as different numbers, even if a rounded printout will not!

    --
    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
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by ralu. View Post
    Here it is another interesting problem:
    Well, no. It's not an interesting problem, it's a floating point inaccuracy, which every programmer should be aware of. Just like buffered stdout. These are not hidden issues that you might never need to know about. This is stuff that anyone who seriously develops software in C has to know!

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  7. #7
    Registered User ralu.'s Avatar
    Join Date
    Feb 2009
    Location
    Bucharest, RO
    Posts
    32
    matsp, QuantumPete i was not expecting the pb to be interesting for you, cause i know it's not... But on this forum are many newbies for whom this is interesting: the result is not what they expect it to be.

    Maybe this you'll find a little more interesting:

    Code:
    void send(register char *to, register char *from, register int count)
    {
      register int num = (count + 7) / 8;
    
      switch(count % 8){
      case 0: do { *to++ = *from++;
        case 7:  *to++ = *from++;
        case 6: *to++ = *from++;
        case 5: *to++ = *from++;
        case 4: *to++ = *from++;
        case 3: *to++ = *from++;
        case 2: *to++ = *from++;
        case 1: *to++ = *from++;
        } while( --num > 0);
      }
    I have stopped reading Stephen King novels. Now I just read C code instead.

  8. #8
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by ralu. View Post
    Maybe this you'll find a little more interesting:
    Duff's Device? You'll have to do better than that

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Old "trying to be clever with memcpy thing" using case-labels inside the loop.
    Yes, it's pretty clever, but if num is fairly large, it would make more sense to check if to and from are aligned, and cast the pointers to a larger type pointer (e.g. long), then copy larger blocks.

    The use of register in modern compilers is at best a no-op, and if the compiler obeys you, may lead to less good register usage than if you do not give a register keyword. In essense: If you have not measured that register gives better performance, do not use it.

    --
    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.

  10. #10
    Complete Beginner
    Join Date
    Feb 2009
    Posts
    312
    adding 0.09999999... together ten times leaves you with a number similar to 0.9999999... which is not precisely 1.0
    For 0.9999... with a finite sequence of digits (as in our machines), this is true. But mathematically speaking, 0.999... is really the same as 1. Here's the proof:

    1 = 3 * (1/3) = 0.999...

    Dividing by 10 yields that 0.1 is the same as 0.09999...

    The fact that 10*.1 != 1. is not due to rounding errors (there's no rounding involved here) but because the machine can only represent a finite number of decimal places.

    Greets,
    Philip
    All things begin as source code.
    Source code begins with an empty file.
    -- Tao Te Chip

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by Snafuist View Post
    For 0.9999... with a finite sequence of digits (as in our machines), this is true. But mathematically speaking, 0.999... is really the same as 1. Here's the proof:

    1 = 3 * (1/3) = 0.999...
    While I agree with your statement, I don't like the proof much..

    I've seen an imho better proof, here's more or less how it goes:
    a = 0.99999...
    10*a - a = 9.99999... - 0.99999... = 9
    10*a - a = 9*a
    9*a = 9
    a = 1

  12. #12
    Complete Beginner
    Join Date
    Feb 2009
    Posts
    312
    While I agree with your statement, I don't like the proof much..
    You are right. My version is rather a hint, while yours might actually be considered a real proof.

    Greets,
    Philip
    All things begin as source code.
    Source code begins with an empty file.
    -- Tao Te Chip

  13. #13
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    How about this for a puzzle. What does the following print out on your console and more importantly, why?

    Code:
    #include <stdio.h>
    int main (void)
    {
        int n = 0;
        for (n = 0; n <= 1; ++n) 
        {
            printf ("%d", n);
            fork();
        }
        return 0;
    }
    QuantumPete
    Last edited by QuantumPete; 03-05-2009 at 10:25 AM. Reason: corrected code
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by QuantumPete View Post
    How about this for a puzzle. What does the following print out on your console and more importantly, why?

    Code:
    #include <stdio.h>
    int main (void)
    {
        int n = 0;
        for (n = 0; n <= 1; ++n )
        {
            printf ("%d", n);
            fork();
        }
        return 0;
    }
    QuantumPete
    Did you mean the amended code above? As your code won't compile...

    And I have a fair idea what it will print...

    --
    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.

  15. #15
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by matsp View Post
    Did you mean the amended code above? As your code won't compile...

    And I have a fair idea what it will print...

    --
    Mats
    Yes, sorry, I've corrected my post. So used to using i as an iterator
    Anyone want to venture a guess?

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. The puzzle again...Swapping elements of 2D array
    By crazygopedder in forum C Programming
    Replies: 44
    Last Post: 11-05-2008, 01:53 PM
  2. Replies: 12
    Last Post: 06-06-2008, 05:26 PM
  3. Crossword Puzzle Program
    By Loctan in forum C++ Programming
    Replies: 2
    Last Post: 07-31-2006, 11:08 PM
  4. Solution to Google Puzzle 3,3,8,8=24
    By LuckY in forum A Brief History of Cprogramming.com
    Replies: 10
    Last Post: 06-01-2006, 09:12 AM