I've occasionally noticed some C code insisting on using 0 - x
to get the additive complement of x
, rather than writing -x
. Now, I suppose these are not equivalent for types smaller in size than int
(edit: Nope, apparently equivalent even then), but otherwise - is there some benefit to the former rather than the latter form?

- 118,144
- 57
- 340
- 684
-
2Actually, being promoted to `int` happens in either case. The only case I see them having a different effect is if `x` is floating-point. – Deduplicator Aug 01 '21 at 21:15
-
*"Now, I suppose these are not equivalent for types smaller in size than int"* - They are actually [6.5.3.3p3](https://port70.net/~nsz/c/c11/n1570.html#6.5.3.3p3). Which makes this somewhat interesting. – StoryTeller - Unslander Monica Aug 01 '21 at 21:15
-
3These days I would just guess readability. In K&R days maybe they want to avoid `y=-x` where `=-` was an alternative token for `-=` – M.M Aug 01 '21 at 21:16
-
5As expected, there is a difference for floating-point zero: https://coliru.stacked-crooked.com/a/bc2ec461b152cefc – Deduplicator Aug 01 '21 at 21:22
-
Maybe because they want to be sure to get the integer promotion (not knowing that it happens in boths cases)? – Bob__ Aug 01 '21 at 21:22
-
3It would be interesting to see where this _occasionally_ comes from. – Roland Illig Aug 01 '21 at 21:22
-
1If i used it, it would be if it was a mathematical context where I want to make clear that a parameter is zero – klutt Aug 01 '21 at 21:41
-
2Depending on toolchain, `unsigned int x; x = -x;` may result in a warning, while `unsigned int x; x = 0 - x;` does not. For floating-point types, unary minus is usually mapped to the IEEE-754 "negate" operation, which is a bit-level operation, not an arithmetic operation. So `-x` behaves different from `0 - x` for zero and NaN operands. – njuffa Aug 01 '21 at 22:39
-
@Deduplicator: That sounds like an answer. – einpoklum Aug 01 '21 at 22:44
-
@RolandIllig: I'm doing some work on a [standalone printf-and-friends implementation](https://github.com/eyalroz/printf/) (forked from [here](https://github.com/mpaland/printf), and it [exhibits this artifact](https://github.com/eyalroz/printf/blob/master/printf.c#L773). I remember seeing this before but I forget where. – einpoklum Aug 01 '21 at 22:48
-
I wonder if the author of that code thought that `0-x` would avoid the bug when `x == LLONG_MIN`. Unfortunately it does not, and there is UB in that case, whether `0-x` or `-x` is used. (Your version has the bug too, btw, and for other signed integer types as well.) – Nate Eldredge Aug 01 '21 at 23:26
-
2This looks like a private joke... Here are more graphic alternatives: `0-x-0` and `x-x-x` (aka *the winning move*) – chqrlie Aug 02 '21 at 08:42
-
1I would say it depends entirely on whether there's a comment on the line of code or not. *If* there's a comment, and if it says something like `/* We don't want an IEEE-754 -0 here */`, there's your answer. But if not, I'd assert there's no reason for it at all, and that the original programmer was likely either careless or confused. – Steve Summit Aug 02 '21 at 13:19
-
1@SteveSummit: No comment :-P – einpoklum Aug 02 '21 at 14:29
-
@NateEldredge: Fixed, albeit in a somewhat brittle kind of way. – einpoklum Aug 02 '21 at 16:45
2 Answers
tl;dr: 0-x
is useful for scrubbing the sign of floating-point zero.
(As @Deduplicator points out in a comment:)
Many of us tend to forget that, in floating-point types, we have both a "positive zero" and a "negative zero" value - flipping the sign bit on and off leaves the same mantissa and exponent. Read more on this here.
Well, it turns out that the two expressions behave differently on positive-signed zero, and the same on negative-signed zero, as per the following:
value of x |
value of 0-x |
value of -x |
---|---|---|
-.0 |
0 |
0 |
0 |
0 |
-.0 |
So, when x
is of a floating-point type,
- If you want to "forget the sign of zero", use
0-x
. - If you want to "keep the sign of zero", use
x
.
For integer types it shouldn't matter.
On the other hand, as @NateEldredge points out the expressions should be equivalent on small integer types, due to integer promotion - -x
translates into a promotion of x
into an int
, then applying the minus sign.

- 118,144
- 57
- 340
- 684
There is no technical reason to do this today. At least not with integers. And at least not in a way that a sane (according to some arbitrary definition) coder would use. Sure, it could be the case that it causes a cast. I'm actually not 100% sure, but in that case I would use an explicit cast instead to clearly communicate the intention.
As M.M pointed out, there were reasons in the K&R time, when =-
was equivalent to -=
. This had the effect that x=-y
was equivalent to x=x-y
instead of x=0-y
. This was undesirable effect, so the feature was removed.
Today, the reason would be readability. Especially if you're writing a mathematical formula and want to point out that a parameter is zero. One example would be the distance formula. The distance from (x,y) to origo is sqrt(pow(0-x, 2), pow(0-y, 2))

- 30,332
- 17
- 55
- 95
-
That's a good observation about the primordial form of the `-=` operator (and other op-equal operators). That may very well explain the source of the idiom the OP asks about. – John Bollinger Aug 01 '21 at 23:05