18

Suppose we have an int and want to toggle it between 0 and 1 in a boolean fashion. I thought of the following possibilities:

int value = 0; // May as well be 1

value = value == 0 ? 1 : 0;
value = (value + 1) % 2;
value = !value; // I was curious if that would do...
  1. The third one seems to work. Why? Who decides that !0 is 1?
  2. Is something wrong with any of these?
  3. Are there other possibilities? e.g. bitwise operators?
  4. Which offers the best performance?
  5. Would all that be identical with _Bool (or bool from stdbool.h)? If not, what are the differences?

EDIT: Many great answers with lots of valuable information, thanks! Unfortunately, I can only accept one.

riha
  • 2,270
  • 1
  • 23
  • 40
  • Who decides that `!0` is `1`? The language specification decides that. So you can rely on it. – Mysticial Oct 31 '12 at 08:44
  • 1
    Differences in performance with simple statements like this are impossible to generalise, it depends on too many variables, not least the compiler, and the differences will probably be trivial. I suggest you concentrate on clarity instead - there are probably more important areas of your code where you should worry about performance. – cdarke Oct 31 '12 at 08:48
  • You can toggle between any two numbers with `sum - value`, where sum is the sum of the two numbers. So in this case: `1 - value`. – potrzebie Oct 31 '12 at 09:23
  • @potrzebie For a signed type, this requires that the sum can be represented. `^` can also be used to the same effect. – Pascal Cuoq Oct 31 '12 at 13:05
  • a^1 gives the best performance in most architectures I can think of (and there are many) -- if _a_ is initialized correctly -- consult my answer for further analysis – Aki Suihkonen Oct 31 '12 at 13:12
  • Not directly related to your question but since you got answers to your question number 1 I just wanted to add that for the very reason explained in the other answers value=!!value; will set any value to 1. A nice little trick. – Waxhead Feb 01 '14 at 17:33
  • You can write `value = (value + 1) % 2;` in a more fancy way like this : `(++value) %= 2` – jahackbeth Jul 16 '16 at 08:17

8 Answers8

33

value = !value; expresses what you want to do directly, and it does exactly what you want to do by definition.

Use that expression.

From C99 6.5.3.3/5 "Unary arithmetic operators":

The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
13

The third one seems to work. Why? Who decides that !0 is 1?

C Standard guarantees that !0 is 1.

Are there other possibilities? e.g. bitwise operators?

Yes, you can use the exclusive OR operator:

value ^= 1;

By the way I prefer this to value = !value; as relational and equality operators can result to branching and bitwise operators usually do not.

ouah
  • 142,963
  • 15
  • 272
  • 331
11
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
                   // when you know initial value is either 0 or 1
Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
  • 1
    I don't know why so little likes. I think this is a beautiful mathematical solution! – 71GA Mar 03 '20 at 08:45
4
  1. the language was designed that way.
  2. Use the 3rd one, the others are right but unnecessarly complicated and therefore hiding the intent.
  3. value = (value ^ 1) & 1;
  4. They're all the same after optimisation.
  5. _Bool would have the same results. The only thing different with _Bool is that values are coerced to be either 1 or 0. Meaning that bool x = 55; will have the value x == 1

EDIT: Corrected the formula in 3 because of my brainfart. I let the comments so that people can see my blooper.

Patrick Schlüter
  • 11,394
  • 1
  • 43
  • 48
  • -2 is 11111111111111110 in binary. It is there to coerce the value to 1 or 0. A simple ^1 would toggle the last bit but let all the other bits as they were. `!33==0` `33^1==32` `(33^1)&-2==0`. Edit: upps, brainfart. It's of cours &1 that should be applied. – Patrick Schlüter Oct 31 '12 at 12:45
  • Ah yeah, that makes sense when "invalid" input (values other than 0 and 1) are possible. – riha Oct 31 '12 at 13:18
4

There can be noticeable performance issues with the alternatives depending on the architecture:

  • !a might need in some architectures comparison and branching, which can be expensive depending on the pattern of 'a'
    • on some architectures there is conditional move (which is branchless), but
      which may require still 3 instructions to complete (with dependencies)
  • 1-a most likely needs two instructions in many architectures
    • counter example: ARM has reverse subtraction RSB %r0, %r0, #1
  • 1^a can be implemented in many architecture with a single instruction
  • a=(a+1) % 2 will be most likely optimized to a=(a+1)&1, which requires 2 instructions

But anyway the first rule of optimization is that don't optimize a non working code. To replace !a with a^1, one has to be 100% certain that it produces always the expected value.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
3

value = !value seems the most reasonable one, but you can also use value = 1 - value or value ^= 1. But the last two would both break if value is not 0 or 1. The first one would still work.

detunized
  • 15,059
  • 3
  • 48
  • 64
1

Your expression value = value == 0 ? 1 : 0; will work exactly like value = !value;. You can use any of the two.

!0 is always 1 and also !(any non zero value) is 0

CCoder
  • 2,305
  • 19
  • 41
0

Use bitwise NOT operator

var = ~var;