C Programming Code Snippet

Discussion in 'Mac Programming' started by cybrscot, Apr 4, 2011.

  1. macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #1
    I'm trying to figure out what's wrong with this code snippet.

    Code:
    while (done = true)
    done = ! done;
    
    I'm not sure what to make of this one? is it just written wrong? Or does it just not do anything?? ?? I think true is being assigned to done, then ! done is being assigned to done. So now done holds the value ! done and gets tested at the top again....argh. Not sure here.

    Or is the error that it should be (done == true)?? Can an assignment be used as an expression? Is that the error?
     
  2. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    done = true assigns the value of true to done, and evaluates to true.
    done == true evaluates to true if done contains the same thing that true does, or false otherwise.

    -Lee
     
  3. macrumors Pentium

    KnightWRX

    Joined:
    Jan 28, 2009
    Location:
    Quebec, Canada
    #3
    What is it you expect the code to do and what is it doing instead ? Have you compiled and run this code ? If you did, you'd instantly know what is wrong.
     
  4. thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #4

    Thanks Lee, yeah I got that, but what's wrong with the code snippet? This is an exercise problem at the end of Chapter 7 in my "Learn C on the Mac" book. They're asking what's wrong with the fragment? It doesn't make sense to me, it seems like it will run forever, as the body assigns ! done to done, basically the opposite of it's previous value, then when done (which now contains ! done) gets tested, it has true assigned to it, then done (containing true) has ! done assigned to it again. ....I guess, is this also an infinite repeating loop?
     
  5. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #5
    Perhaps that is what is wrong with the fragment... :)
     
  6. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #6
    When asking "what's wrong?" you sort of need to know what it SHOULD do. If this should exit after 0/1 iterations, then running infinitely would be a problem. If it is supposed to constantly switch "done" from one state to another forever, it is working properly.

    -Lee
     
  7. thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #7
    Yeah, who knows what it's supposed to do. At the top of the page it just says "What's wrong with each of the following code fragments", then has 8 different sets of code fragments. Some of them have syntax errors, this one appeared to be syntax error free, but I can only assume that it's looping forever is the problem, just wanted to get another pair of eyes on it. A couple of the previous ones were also infinite loops. I guess the reader is supposed to walk through these examples, see that they are infinite loops (although at first glance they don't appear to be) and assume that it's not optimal code for a loop. While there are better ways to write a loop if you intend to write one.

    Thanks guys.
     
  8. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #8
    Confusing assignment and comparison operators is a syntax error. Sure it'll compile, but it's clearly not what was intended.

    You have to be careful with a few aspects of this in C.
    • There is no proper Boolean type.
    • true/false are not specified by default.
    • Assignment returns the right hand side of the assignment.

    So if the rest of the code looked like:

    Code:
    int true = 0;
    int done = 1;
    while (done = true)
    done = ! done;
    
    The code would loop exactly no times.

    B
     
  9. admanimal, Apr 4, 2011
    Last edited: Apr 4, 2011

    macrumors 68040

    Joined:
    Apr 22, 2005
    #9
    You have just described exactly why this is a semantic error and not a syntax error. Syntax errors are caught by the compiler. Semantic (i.e. logic) errors usually mean that the code runs but is not doing what you intend it to do. Granted the line is a bit fuzzy here since the logic error is clearly caused by an unintentional misuse of otherwise correct syntax.
     
  10. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #10
    Sorry, I made it worse by deleting a paragraph. The gist of it was:

    If C actually defined a proper Boolean type this would be more likely to actually be caught by the compiler.

    (NOTE: The reason I deleted it is if both done and true were good Boolean variables rather than constants and assignment still returned the right hand side, the code would be OK again, but would still be a null or infinite loop depending on the value of true).

    B
     
  11. macrumors 68040

    Joined:
    Feb 2, 2008
    #11
    C99 introduced stdbool.h, which defines a boolean type and true, false constants. In the end though, this is still an integer type.

    Would be interesting to know if there are a language that actually has boolean type, where:

    Code:
    if(a)
    is not the same as:

    Code:
    if(a == true)
     
  12. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #12
    Fortran has a Boolean type. The Boolean literal for true is .true. and equivalence was only .eq. prior to fortran 90 when == was added. So the first statement, assuming a is boolean, is legal. The second isn't valid at all before fortran 90, and after fortran 90 I'm pretty sure you could declare true as a Boolean variable and set it to .false., yielding the opposite result of the first statement.

    -Lee
     
  13. macrumors 6502a

    Joined:
    Jun 27, 2010
    #13
    Isn't that an infinite loop?
     
  14. macrumors 68040

    Joined:
    Feb 2, 2008
    #14
    I guess I'm confusing things a bit here, if a is declared as: int a = 10;

    Then the first statement evaluates to true, since in C true is anything non zero.
    Yet: true is defined as 1. meaning the second statement is false given the value of a. So maybe any value that is not zero should pass that condition as well, given that any non zero values is supposed to be true. Or perhaps it should be an error disallowing comparisons between ints and bools.
     
  15. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #15
    If the hypothetical language allowed implicit coercion from its integer type to its boolean type such that a non-zero integer is coerced to boolean true and therefore the code if (a) is valid, I would hope the same logic work prevale in the code if (a == true). That is a would be coerced to boolean true resulting in a boolean comparison. And not that boolean true would be coerced to integer 1 resulting is a dubious integer comparison.

    But I'm sure one could find a language that did behave as in the later case. That's one of the reasons I liked coding in Ada in my last major project. Ada has no (or a least very limited) implicit coercion. If you wanted to code if (a == true) in Ada where a is an integer, you'd need to explicitly typecast one to the other to make your intent clear.
     
  16. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #16
    And that's why context is critical.

    Without stdbool, true is just a variable that could be defined as anything, including zero. (larswik just posted a Pascal thread where he effectively implicitly defined true as zero.) For all we know it's a float or char *.

    "a = true" will evaluate to the value of true, but if true has the value 0 (i.e. not using stdbool or locally overriding it) this will be interpreted as a logical false. (C has this nice behavior that allows stuff like "a = (b = 10);" to work since "b = 10" evaluates to 10.)

    And that's basically why the paragraph I deleted in the earlier post was deleted. It was getting a bit hypothetical and far above where I think cybrscot is.

    Ultimately, the code snippet in question should be avoided for a multitude of reasons.

    I usually err on the side of accepting that C doesn't have a boolean type and would write "while (done)" [or preferably "while (!done)" if I intended a loop :p] instead of "while (done == true)" and I would avoid putting "work" in the loop condition as we saw many examples of in cybrscot's for loop thread from the KN King book. You can interpret the original code snippet as:

    Code:
    while (true) {
    done = true;
    done = ! done;
    }
    It then becomes clear that its behavior only depends on the value of true.

    B
     
  17. macrumors 68040

    Joined:
    Feb 2, 2008
    #17
    Yes but I was referring to the second case: if(a == true) and using the standard C definition of true in stdbool. It will evaluate to false for any values of 'a' but 1 (on mac OS at least). Basically, to get the statement working in a logic sense you would need something like: if( (a == 10) == true ) which is a bit weird. But given that 'a' is an integer, it's not that weird compared to asking if 'a' is true, since it can hold 2^32 different values.

    IMO you shouldn't use stdbool 'true' on anything not declared as bool. This is an error in for example Java, and for good reasons.

    Except if 'done' is declared as a bool, which makes sense unless your accepting more states than 2, like half-done and so on.:p
     
  18. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #18
    I thought I was being clear that I was advocating accepting that done is an int in C and NOT using stdbool. (Apparently I wasn't being as clear as I thought ;).).

    B
     
  19. macrumors 68040

    Joined:
    Feb 2, 2008
    #19
    Well, if you try this:

    Code:
    bool test = 10;
    printf("%d\n", test);
    
    It prints 1. So, if you are going to use true/false in a program I think stdbool makes sense.
     
  20. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #20
    Ick! I know that works, but it exactly the kind of mixed message I'm seeking to avoid.

    If you use stdbool you should strive to use only true/false as values for bool variables, not even (1/0). (As other languages with a real strong Boolean would force you to). If you want to use the looser, standard C behavior where false is zero and true is anything but, don't use stdbool and accept that true and false are ints.

    At least do:

    Code:
    #include <stdbool.h>
    bool test = (10 != 0);
    printf("%d\n", test);
    
    However that's just MHO.

    B
     
  21. macrumors 68040

    Joined:
    Feb 2, 2008
    #21
    It's there just to demonstrate that it's not the same as declaring 'done' as an int. You would not do that in reality but instead: bool done = true;

    Thus true/false tests will always work for 'done', unlike if 'done' was an int where only one value out of all 2^32 will evaluate to true.
     
  22. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #22
    Chickens and eggs. It only becomes an issue when you try to mix bool and int. So don't. (Again, just MHO).

    If you don't use stdbool true/false tests (i.e. if statements, ternary statements, etc...) will always work for an int and there are 2^32-1 trues and one false.

    You could replicate the behavior you see using bool without stdbool using a ternary statement in the printf. "done?1:0;".

    B
     
  23. macrumors 68040

    Joined:
    Feb 2, 2008
    #23
    Well that is what I'm saying.

    Again, in the context here what we are talking about is evaluations of this test:

    Code:
    if(a == true)
    Where 'a' is in an int, it's only 1 value that is true, not all 32^2 values except zero.

    I know that you are referring to:

    Code:
    if(a)
    if(!a)
    
    And so on, but..
     
  24. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #24
    I know we're not disagreeing, but I think it is a point worth discussion.

    The problem IMHO is that given only the snippet of code in the first post, we don't know if stdbool.h is included or not so if true is defined as we might expect or not.

    Generally, a == true is superfluous so don't use that form. If a is an int, you need a to be the one out of 2^32 values defined by true which is probably not the behavior you want. If a is a bool then it is already either true or false so what is the point of the comparison?

    Try this one:

    Code:
    #include <stdio.h>
    #include <stdbool.h>
    
    int main(void)
    {int a=10;
    
    if(a==true) printf("a is true!\n!");
    else printf("a is false!\n");
    
    if((bool)a==true) printf("a is true!\n!");
    else printf("a is false!\n");
    
    return 0;
    }
    
    Bad juju, but again that's just MHO.

    B
     
  25. macrumors Pentium

    KnightWRX

    Joined:
    Jan 28, 2009
    Location:
    Quebec, Canada
    #25
    The point was to use an assignment operator instead of a comparison operator to create an infinite loop so that the reader could identify the operator used in the loop's condition as the fault of the code snippet.

    Remember guys, these are book exercises with a precise goal. The snippets might not make sense in a real world application, they are purely academic validations.
     

Share This Page