10

Do C conditional statements always return [1 or 0], or do they return [0 or 'something other than zero']. I ask because:

pseudo code -

foo(address, shouldSend):
register >>= 1
register <<= 1 // to clear bit in first position
register |= shouldSend // to signal whether it should send or not

the problem occurs if somebody passin IN a shouldSend value of true greater than one (as only 0 is false and all else is true, technically this is valid). since i am directly OR'ing the truth value of shouldSend with the register, it better not be say 0xFF! i already have a solution, so the question is more for curiousity sake. i am wondering though if:

foo(address, shouldSend):
register >>= 1
register <<= 1 // to clear bit in first position
register |= (shouldSend > 0) // to signal whether it should send or not

solves the problem? i would think that now the problem of an 0xFF(or in general, something greater than 1) passed in is masked by the C conditional. but this only holds IF C conditionals are guaranteed to return [0 or 1].

ps - i also realize that it is probably compiler dependent, but what does the ansi standard say about this?

trh178
  • 11,228
  • 5
  • 28
  • 37

4 Answers4

23

Standard specifies that the result is always integer value equals to 0 or 1

6.5.8 Relational operators

Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.92) The result has type int.

Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • 1
    +1, quite surprising that it does indeed specify that behavior. Over time I just assume that the spec would be more likely to say "returns 0 or random roll of the dice" – JaredPar Aug 20 '10 at 15:35
  • 2
    This leads to the idiom I've seen used since before there was a standard: `!!somevalue` which has the same truth value, but which is now guaranteed to be exactly 0 or 1. – RBerteig Aug 20 '10 at 18:25
1

Doesn't matter if it is specified or not. It is best to always test against false and be explicit about your or-equals values. This removes any worry about compiler implementations and is clearer and more maintainable.

Ken
  • 21
  • 1
  • That's actually relevant, since you could use & and | operators as logic operators WITHOUT short-circuiting. – Spidey Apr 30 '12 at 19:44
1

Rather than right shifting and left shifting back again to clear the LSB, I would bitwise-and it with 0xFE:

register = register & 0xFE;

[edit: assuming register is 8 bits. If not, adapt right hand operand as necessary]

But yes, if shouldSend is a result of a conditional test then it is guaranteed by the standard to be either 0 or 1. If there's any doubt about whether shouldSend could be generated from anywhere else it would be wise to put in the sort of precaution you have, or something like

register = register | (shouldSend ? 1 : 0);
Vicky
  • 12,934
  • 4
  • 46
  • 54
  • 1
    The idiom I've seen used since before there was a standard: `!!somevalue` which has the same truth value, but which is now guaranteed to be exactly 0 or 1. – RBerteig Aug 20 '10 at 18:25
0

Yes. This is guaranteed in C99. I don't have the C89 spec handy. Of course, compiler implementers have been known to make mistakes on occasion so YMMV.

C99 specifies the following in paragraph 6 of 6.5.8 Relational operators:

Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.

The same or similar clauses appear in paragraph 3 of 6.5.9 Equality operators, paragraph 3 of 6.5.13 Logical AND operator, and paragraph 3 of 6.5.14 Logical OR operator.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113