<p>Many languages have compound assignment statements, for example <code>+=</code>. However, for the common task of adding or subtracting 1 from a variable some languages (mostly those close to C) have additional <code>++</code> and <code>--</code> operators. For example, <code>x += 1</code> can be written as <code>x++</code> in these languages. Some languages decide not to have these operators. This can make some sense, as there is already a short way to increment something. Why would you add an increment/decrement operator when you have compound assignments? For completeness, I'll allow arguments for the other position as well.</p>

<operators><assignment>
Why add an increment/decrement operator when compound assignments exist?
CC BY-SA 4.0
2023-07-08T00:42:29.843Z
I think the reason is that the specialized corresponding add/subtract by 1 instructions exist in Assembly.
CPlus
CC BY-SA 4.0
2023-07-08T14:14:35.103Z
FYI, the increment/decrement operators came first. C inherited them from B, which didn't have compound assignments. The latter were a generalization that was added in C.
Barmar
CC BY-SA 4.0
2023-07-10T19:43:54.667Z
For one thing, "C+=1" would be an awful name for a programming language.
bta
CC BY-SA 4.0
2023-07-10T20:40:40.000Z
Why add compound assignment operators when separate assignment and arithmetic operators exist?  Some languages choose not to have compound assignment operators.  This can make some sense, as there is already a way to increment / decrement / *etc*. something.  Why would you add compound assignments when you already have ordinary assignment and ordinary arithmetic operators?
John Bollinger
CC BY-SA 4.0
2023-07-10T21:05:37.043Z
In PDP-11 assembly (other assembly languages were likely similar), `++` and `+=` were natural representations for `INC` and `ADD`. Whereas in assembler you'd write `MOV X, Y; ADD X, Z` (`x = y; x += z;` in C), C allowed you to write `x = y + z`. The fact that `x += 1` and `x++` are equivalent in the semantics of C doesn't change that fact that `INC X` was cheaper in several ways than `ADD X, 1`.
chepner
<p>There are some important semantic differences between increment and decrement operators vs the addition and subtraction assignment operators.</p>
<p>Consider an iterator walking some kind of data structure like an array vs an expensive generator function.
It may not be possible to jump to the Nth element without computing the intermediate elements first.</p>
<p>So while:</p>
<pre><code>iter += 3
</code></pre>
<p>is equivalent to:</p>
<pre><code>iter.next().next().next()
</code></pre>
<p>and indeed you can <a href="https://en.wikipedia.org/wiki/Peano_axioms" rel="nofollow noreferrer">construct the whole of arithmetic</a> this way, it is not necessarily efficient.</p>
<p>Defining a additional assignment operator can be used to imply that there is a short cut.</p>
<p>In some languages it is useful to imply the computational cost but not defining additional assignment if it is not efficient.</p>
<p>So for a number type you can easily do:</p>
<pre><code> x = 1;
 x += 5;  // what it looks like - just a simple addition operator
</code></pre>
<p>It would seem less intuitive to write:</p>
<pre><code> class iterator
 {
     calculate_next();
     opeator++() { calculate_next(); }
 };

 foo++   // fine as alias for calculate_next;
 foo+=5  // less obvious as an alias for calculate_next repeated 5 times;
</code></pre>
<p>There is potentially a loop in the second case which does not exist in the first case. Though it gives the right answer, Peano arithmetic is not computationally efficient.</p>
<p>Another difference is that increment and decrement tend to be usable as expressions while addition assignment tends to useable only as a statement.</p>
<pre><code> x+=2
</code></pre>
<p>is more intuitive than:</p>
<pre><code> y=(x+=2)
</code></pre>
<p>If used as an expression it would also be a pre-increment whereas x++ is a post increment.</p>
<p>With increment and decrement operators (in C and C++ at least) you can define whether the value is incremented before or after the return.</p>
<p>That is in the context of:</p>
<pre><code> y=++x;

 ++x    
</code></pre>
<p>means:</p>
<pre><code> x=x+1;
 return x;
</code></pre>
<p>Whereas in the context of:</p>
<pre><code> z=x++;

 x++
</code></pre>
<p>means:</p>
<pre><code> ret=x;
 x=x+1;
 return ret;
</code></pre>
<p>Thus:</p>
<pre><code> y &gt; z
</code></pre>
<p>All this is true even without considering the historical origins of increment and decrement in relation to C as a layer on top of assembly languages which may themselves have distinct increment and addition operations.</p>

CC BY-SA 4.0
2023-07-08T08:16:05.450Z
2023-07-10T10:34:52.557Z
2023-07-10T10:34:52.557Z
Bruce Adams
CC BY-SA 4.0
2023-07-10T09:33:21.227Z
This is the most compelling reason, IMO.
leftaroundabout
<p>There are some good long answers. The short one is that it makes working with arrays and other containers with dense index-based access easier, shorter and less error prone. You can easily misstype 2 instead of 1.</p>

CC BY-SA 4.0
2023-07-08T09:11:02.133Z
2023-07-08T09:11:02.133Z
feldentm
<p>The <code>++</code> and <code>--</code> operators aren't really necessary.  There are languages that get along just fine with <code>x += 1</code> and <code>x -= 1</code>.  Like Python, or Swift (which <em>had</em> these operators <a href="https://github.com/apple/swift-evolution/blob/main/proposals/0004-remove-pre-post-inc-decrement.md" rel="noreferrer">but <em>removed</em> them for being error-prone</a>).</p>
<p>But because incrementing or decrementing a variable by 1 is extremely common (especially in a <code>for</code> loop), and because PDP-11 assembly language happened to make it easy to implement those operations, C's designers decided to provide <code>++</code> and <code>--</code> as syntactic sugar.  And then a bunch of other languages decided to adopt the C syntax for their operators.</p>

CC BY-SA 4.0
2023-07-07T21:51:35.013Z
2023-07-07T21:51:35.013Z
dan04
CC BY-SA 4.0
2023-07-08T08:22:28.430Z
This strikes me as a huge facepalm ‍♂️ for swift. Their reasoning seems unsound given that they acknlowedge both the difference between statements and expressions (one returns a value) and the difference between pre and post increment. Perhaps there is some context in how people tend to write swift code.
Bruce Adams
CC BY-SA 4.0
2023-07-08T10:13:02.213Z
I couldn't disagree more with Swift's decision, but +1 for this as an answer to the question asked.
Jack Aidley
CC BY-SA 4.0
2023-07-08T19:21:42.663Z
@BruceAdams: Yeah, I'm not experienced with Swift, but the decision seems weird.  They could have just changed the return value of the operators to `Void`, which would still allow `x++` and `x--` as standalone statements, while avoiding confusing uses like `f(++x, x++)`.
dan04
CC BY-SA 4.0
2023-07-08T19:51:59.343Z
@dan04 What would be the point of having `x++` and `++x` if they wouldn't return anything? The only difference between them is what they return.
xigoi
CC BY-SA 4.0
2023-07-08T19:57:36.313Z
@xigoi: Just backwards compatibility.  Both `x++` and `++x` would become redundant ways of spelling `x += 1` as a standalone statement.
dan04
CC BY-SA 4.0
2023-07-09T13:23:20.453Z
The reference given doesn't support that Swift removed those operators because they'd be "error prone".  They are giving mostly different reasons for their decision in the reference.
Jirka Hanika
CC BY-SA 4.0
2023-07-09T13:30:47.323Z
Operator `--` is useful to implement `while (u-- > 0) {...}` where u is an unsigned.  The "equivalent" `while (u -= 1 >= 0) {...}` would results in an infinite loop.
Florian F
CC BY-SA 4.0
2023-07-09T14:42:29.990Z
Rust is another example that has `+=` but not `++`.
Nayuki
CC BY-SA 4.0
2023-07-10T09:20:30.437Z
@dan04 removing an operator altogether _is_ the safest option. It guarantees that anybody compiling a piece of code containing the operator sees a clear and to the point error message, which will be easy to fix. Only changing the type bears the risk of confusion. Shouldn't really be a problem for something as simple as `++`, but on the other hand this is also the kind of thing that already first-week beginners will be exposed with, and they might struggle.
leftaroundabout
<p>(Yes, I'm writing another answer to this question.)
Sometimes <code>i++</code> really is what you need.
Here's an example where it shines. Consider the following code fragment:</p>
<pre><code>int index = 0;
Set(index++, &quot;Draw&quot;);
Set(index++, GetDistance());
Set(index++, GetColor());
Set(index++, GetOptions());
</code></pre>
<p>How would you write that in a language that doesn't have, specifically, the postfix increment operator?</p>
<hr />
<p>You could use constants:</p>
<pre><code>Set(0, &quot;Draw&quot;);
Set(1, GetDistance());
Set(2, GetColor());
Set(3, GetOptions());
</code></pre>
<p>But this is error prone! If you ever need to reorder these lines, or to insert another line, or to delete one of those lines, it's easy to forget updating the index constants.</p>
<hr />
<p>You could use compound assignment:</p>
<pre><code>int index = 0;
Set(index, &quot;Draw&quot;);
index += 1;
Set(index, GetDistance());
index += 1;
Set(index, GetColor());
index += 1;
Set(index, GetOptions());
index += 1;
</code></pre>
<p>But this is twice as many lines of code! And the alternation of lines isn't as easy to inspect... We make this look better:</p>
<pre><code>int index = 0;
Set(index, &quot;Draw&quot;); index += 1;
Set(index, GetDistance()); index += 1;
Set(index, GetColor()); index += 1;
Set(index, GetOptions()); index += 1;
</code></pre>
<p>But now the code is unaligned, again it is not easy to verify that the repeated part is correctly done and no <code>index += 1</code> was forgotten (imagine longer lines). We can do better by moving the similar part towards the beginning of the line:</p>
<pre><code>int index = -1;
index += 1; Set(index, &quot;Draw&quot;);
index += 1; Set(index, GetDistance());
index += 1; Set(index, GetColor());
index += 1; Set(index, GetOptions());
</code></pre>
<p>Now the code is compact and easy to verify again... But the index starts at -1, that's weird!</p>
<hr />
<p>You could introduce a separate function:</p>
<pre><code>int ReturnAndInc(int &amp;i) { *i += 1; return *i; }
[...]
int index = 0;
Set(ReturnAndInc(&amp;index), &quot;Draw&quot;);
Set(ReturnAndInc(&amp;index), GetDistance());
Set(ReturnAndInc(&amp;index), GetColor());
Set(ReturnAndInc(&amp;index), GetOptions());
</code></pre>
<p>Now this is good! Code is compact, it's easy to insert/delete/update lines, it's easy to verify that the index is good!</p>
<p><strong>But we basically reimplemented <code>i++</code>.</strong></p>
<hr />
<p>Looks like sometimes <code>++</code> is useful after all. Now, this doesn't mean it <em>needs</em> to be built-into the <em>language</em>! The last solution can be acceptable, even more so if it can inline ReturnAndInc.</p>

CC BY-SA 4.0
2023-07-08T08:04:53.767Z
2023-07-08T08:04:53.767Z
Eldritch Conundrum
CC BY-SA 4.0
2023-07-08T08:08:21.533Z
You could also have the helper function do both the increment and the call to Set... But what if Set has overloads? Now you need to make many similar helper functions, kept in sync with the number of overloads... I didn't want to include that case in the answer.
Eldritch Conundrum
CC BY-SA 4.0
2023-07-08T08:24:08.750Z
Yuck. Modern language design includes elements of adding syntactic sugar to remove boilerplate. Removing it for something so common seems wrong.
Bruce Adams
CC BY-SA 4.0
2023-07-08T14:55:55.303Z
You could use `i = -1; Set(i += 1, "Draw"); Set(i += 1, GetDistance()); etc.` too, but that's also a bit awkward and then not everyone likes using (compound) assignments as expressions. Then again, why doesn't your `Set()` thingy have an append-like function that would keep track of the last used / first free index?
ilkkachu
CC BY-SA 4.0
2023-07-08T19:17:27.587Z
Swift, in which `++` was removed, also decided to have `+=` return void... And making a `Set()` that also increments the index is boilerplate work that might not always pay for itself, compared to sprinkling some `++`.
Eldritch Conundrum
CC BY-SA 4.0
2023-07-08T19:54:26.157Z
Honestly I think the version that uses the constants is the most clear one. If you have a lot of these you can just iterate an integer range instead of mutating a variable.
Aiono
CC BY-SA 4.0
2023-07-08T20:46:10.140Z
Personal experience: I've tried using the constants. I've had to fix the resulting bugs.
Eldritch Conundrum
CC BY-SA 4.0
2023-07-09T20:00:02.497Z
@Aiono As soon as you're doing it an unknown number of times tho, such as in a loop, that falls apart. Or if `index` starts at an unknown value.
rydwolf
CC BY-SA 4.0
2023-07-10T09:27:13.943Z
"You could also have the helper function do both the increment and the call to Set" - well you _should_! `template<typename... A> set_incr(index, A... args) {set(index, args...); index+=1;}` or something like that. Ok, many languages don't have variadic templates, but most nowadays have at least some form of parametric polymorphism, that should be enough. Alternatively: this really looks like something that should happen in a [state monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)#State_monads).
leftaroundabout
CC BY-SA 4.0
2023-07-10T17:47:15.303Z
You could do that... What if some of the `Set()` are actually `SetDifferently()`? You could add more boilerplate... Or type `++`.
Eldritch Conundrum
<p>While <code>x += 1</code> may be replaced by ++x, x++ is special in that it is essentially <code>temp = x, x += 1, temp</code>. I am making a C-like which is an evolution of C, so removing x++ was never even something I considered, but I will also say that I prefer to have <code>++x</code> and <code>x += 1</code> because they <em>communicate different things</em> in the code if both are available in the language.</p>
<p><code>++x</code> tells me: &quot;increment to the next value&quot;. That is, we're iterating over something. This might be walking through an array or looking at every value in a range. But it is not making any jumps or anything.</p>
<p><code>x += 1</code> on the other hand is saying &quot;increase x by one&quot;, so this could be to adjust something by one, or jumping some amount, which just happened to be <code>1</code> but could just as well have been 2 or 5. Typically I would assume this means we're not using x to iterate (when ++ and -- exists in the language), and x += 1 is that hint.</p>
<p>That said, they are conveniences and can be dropped. Going as far as saying they're &quot;actively harmful&quot; like Swift does, seems like a very extreme opinion.</p>

CC BY-SA 4.0
2023-07-08T00:36:27.973Z
2023-07-08T00:36:27.973Z
Nuoji
CC BY-SA 4.0
2023-07-08T00:57:06.997Z
Yes, I've always been bothered by the use of `x++` when `++x` is appropriate. I know modern compilers will generate the same code, but my ancient brain still sees it as `(temp = x, x += 1, temp)`.
Ray Butterworth
CC BY-SA 4.0
2023-07-08T06:31:17.383Z
@RayButterworth Hey, it sounds better like that ngl (my brain is probably not as ancient).
Syed M. Sannan
CC BY-SA 4.0
2023-07-08T07:33:07.910Z
@Ray  Modern compilers cannot generate the same code for each. For the actual increment or decrement, maybe. But the difference is that the ++a uses the new value immediately, wheras a++ continues to use the old value. The distinction is only resolved at the next "sequence point" (typically end of statement), which opens the door to a hatful of UB.
Paul_Pedant
CC BY-SA 4.0
2023-07-09T08:24:48.177Z
If you look at it in SSA form the code will be pretty much identical, showing how the old value of x can easily be kept in a register. If you have `int b = a++`, then it's also possible to think of that as `int b = a; a += 1;`. The lack of sequence points is just by definition in C. A language can easily decide UB due to ++ and -- well defined.
Nuoji
CC BY-SA 4.0
2023-07-10T01:43:30.030Z
@Paul_Pedant they can generate the same code in cases where the value isn't observed until *after* that sequence-point, which is true in the (extremely) common case where `x++` is a statement on its own.
hobbs
CC BY-SA 4.0
2023-07-10T14:14:02.493Z
`++x` _shouldn't_ tell you "increment to the next value", if `x` is a floating-point type...
Toby Speight
CC BY-SA 4.0
2023-07-10T20:42:43.427Z
@Nuoji I don't know Swift well, but looking at the assignment operator in the language reference, it looks like the assignment "operator" is really a statement (in that an assignment has no value of its own), and from that standpoint an *expression* that has both a value and a side effect is something that modern languages tend to frown upon.
chepner
CC BY-SA 4.0
2023-07-11T09:06:46.320Z
@chepner you just described almost every procedure call in imperative and OO languages. I don't think that is a valid point.
Nuoji
CC BY-SA 4.0
2023-07-11T12:49:40.657Z
There's a difference between a function/procedure call that returns a value (even if it's a trivial value like `void`, `()`, `None`, etc) and something like a `for` statement that has no conceptual value at all.
chepner
<p>C isn't a language that comes with fancy iteration constructs like <code>foreach</code> or <code>map</code>. This means programmers need to increment something <em>every time</em> they loop over indices of an array or a string, or over pointers.</p>
<p>Making <code>i++</code> a shorthand for <code>i += 1</code> makes a little more sense when you're going to spend so much time writing <code>for (int i = 0; i &lt; n; i++)</code> or <code>for (p = s; *p; p++)</code> all over again.</p>
<p>Maybe more interestingly, even though <code>+=</code> is more general and more powerful than <code>++</code>, <strong>more power might be bad</strong>. Having increment be distinct from compound assignment means you are encouraged to think at a different level of abstraction.</p>
<p>You're not &quot;using the full power of addition&quot;, you're just <em>doing the loop thing</em>.</p>
<p>You don't need to visually slow down to verify that you're actually adding the digit <code>1</code> instead of a lowercase <code>l</code> that crept in here, you're just <em>doing the loop thing</em>.</p>
<p>To make this point clearer, I could make a parallel with <code>while</code> being a distinct, less powerful version of <code>goto</code> (remember: more expressive power isn't necessarily a good thing). Reading a <code>goto</code> instills fear in me, and makes me read the entire function again because otherwise I might miss some subtle control flow possibility. Reading a <code>while</code> is just reading a regular, well-known and well-delimited local construct.</p>
<p>In a way, it is the same for <code>++</code>. (And for equivalents in other languages, like <code>inc</code> in Pascal/Delphi.)</p>

CC BY-SA 4.0
2023-07-07T21:44:42.933Z
2023-07-07T21:44:42.933Z
Eldritch Conundrum
CC BY-SA 4.0
2023-07-07T21:52:39.303Z
I would disagree. I've had to write loops with `i += 2`, or 4, or 8 rather than 1 enough times that it doesn't bother me when I see a for loop written that way. Heck, I've even sometimes seen those desugared into while loops, and the overall result is just as readable.
Bbrk24
CC BY-SA 4.0
2023-07-08T07:22:40.750Z
I don't think loops with `+=` are less readable at all. I'm saying it's harder to *confuse* a `++` loop with a `+=` loop.
Eldritch Conundrum
<blockquote>
<p>Why add an increment/decrement operator when compound assignnments exist?</p>
</blockquote>
<p>Why add compound assignment when regular assignment exists? After all, in C, <code>x += 1</code> is equivalent to <code>x = x + 1</code>. Going further, there are many things that look redundant: why have all three of <code>do..while</code>, <code>while</code> and <code>for</code>? Why have loops to begin with if you can use <code>goto</code> or recursion instead? Why do CPUs have all these instructions when <a href="https://stackoverflow.com/questions/61048788/why-is-mov-turing-complete">x86's <code>mov</code> instruction is Turing complete</a>?</p>
<p>Languages are created to make programming <em>more easy</em>, but you also have to remember that you need to be able to create an interpreter and/or compiler for it. It's easy to forget that when <a href="https://en.wikipedia.org/wiki/K%26R" rel="noreferrer">K&amp;R</a> released their first specification of C, most consumer computers were still using 8-bit processors, and 64 kiB of RAM was considered a large amount. The <a href="https://en.wikipedia.org/wiki/PDP-11_architecture" rel="noreferrer">PDP-11</a> that C was developed on was a 16-bit computer which could be made to support up to 4 MiB of RAM, but programs were still limited to a 16-bit address space. So compilers couldn't be very fancy.</p>
<p>As dan04 already mentioned, the PDP-11 had pre- and post-increment operations in its instruction set. So having increment/decrement operators in the language that are easy to parse and easy to generate instructions for makes a lot of sense. Also, consider that incrementing by one is an extremely common operation (already mentioned in several other answers), so it makes programming in C more easy. Consider this string copy function, which is just a one-liner when using post-increment on the pointers:</p>
<pre><code>void strcpy(char *dst, const char *src) {
    while((*dst++ = *src++));
}
</code></pre>
<p>Some people object to this because they find it hard to follow. What if I write:</p>
<pre><code>x = f(x++, x++);
</code></pre>
<p>Even if it's well-defined it's hard to tell what this does without knowing exactly what the rules are for the ordering of operations here. It's worse if it's implementation-defined what will happen. That's an argument against these operators.</p>

CC BY-SA 4.0
2023-07-08T11:24:57.617Z
2023-07-08T11:30:33.057Z
2023-07-08T11:30:33.057Z
G. Sliepen
CC BY-SA 4.0
2023-07-08T19:55:51.440Z
`x += 1` is not necessarily equivalent to `x = x + 1` if you substitute a more complex expression for `x`, such as `arr[rand() % arr_len]`.
xigoi
CC BY-SA 4.0
2023-07-08T21:10:08.260Z
@xigoi True, but you can easily work around that without needing compound assignment. My point is that a lot of things in languages are not really necessary, even if they are very convenient.
G. Sliepen
<p>C had those operators because C was designed to mirror the assembly of the particular machine it was developed for. Some modern languages have no such operator -- Swift in particular cited that <code>++</code> and <code>--</code> were &quot;actively harmful&quot;.</p>

CC BY-SA 4.0
2023-07-07T21:18:37.617Z
2023-07-07T21:18:37.617Z
Bbrk24
CC BY-SA 4.0
2023-07-08T00:54:11.717Z
It wasn't exactly designed for the purpose of mirroring the machine language; it was designed to take advantage of it. Compiling `++x` trivially generated a single instruction. Compiling `x+=1` would require testing for the 1 value in order to decide to handle that special case, which would make the compile take longer. (And yes, compilers really were very slow, so any time saving was worth it.)
Ray Butterworth
<p>In many cases, <code>++</code> and <code>--</code> are used to move to the &quot;next&quot; thing or the &quot;previous&quot; thing.  Although this is equivalent to adding 1, the essential concept embodied in the operation is &quot;next&quot; or &quot;previous&quot;, and not &quot;1&quot;.(*)</p>
<p>The situation is somewhat analogous to the way many languages allow a programmer to write <code>if (flags &amp; BITMASK) ...</code> rather than <code>if ((flags &amp; BITMASK) != 0)</code>.  One might describe the former operation as &quot;is the set of bits in common between the two values non-empty&quot; and the latter as &quot;is the set of bits of values equal to something other than the empty set&quot;.</p>
<p>IMHO, good languages should avoid requiring programmers to write &quot;phony constants&quot;.  If there's only one constant value that has a certain property, having a construct that embodies that property is cleaner than requiring that programmers specify the explicit construct.</p>
<p>(*) This becomes especially true if one views bytes of memory as being located <em>between</em> addresses, but with the convention that a single address will by default refer to the immediately following storage.  Under this view, a 16-byte region of memory will have 17 addresses, with all but the last each uniquely pointing to the start of a byte, and all but the first each uniquely point to the end of a byte.</p>
<p>Viewing memory in this fashion, &quot;incrementing&quot; a pointer means that it should be made to identify an object that starts where the current object ends, and &quot;decrementing&quot; a pointer means it should be made to identify an object that ends where the current object starts.  Note that in this scenario, there would be no space between the previously and newly identified objects.</p>

CC BY-SA 4.0
2023-07-08T18:22:35.203Z
2023-07-09T15:28:46.253Z
2023-07-09T15:28:46.253Z
supercat
# Why add an increment/decrement operator when compound assignments exist?
Posted by: username_0 on 2023-07-07
Many languages have compound assignment statements, for example `+=`. However, for the common task of adding or subtracting 1 from a variable some languages (mostly those close to C) have additional `++` and `--` operators. For example, `x += 1` can be written as `x++` in these languages. Some languages decide not to have these operators. This can make some sense, as there is already a short way to increment something. Why would you add an increment/decrement operator when you have compound assignments? For completeness, I'll allow arguments for the other position as well.
**Tags:** operators assignment
> **Comments:**
> **username_1**: I think the reason is that the specialized corresponding add/subtract by 1 instructions exist in Assembly.  
> **username_2**: FYI, the increment/decrement operators came first. C inherited them from B, which didn't have compound assignments. The latter were a generalization that was added in C.  
> **username_3**: For one thing, "C+=1" would be an awful name for a programming language.  
> **username_4**: Why add compound assignment operators when separate assignment and arithmetic operators exist?  Some languages choose not to have compound assignment operators.  This can make some sense, as there is already a way to increment / decrement / *etc*. something.  Why would you add compound assignments when you already have ordinary assignment and ordinary arithmetic operators?  
> **username_5**: In PDP-11 assembly (other assembly languages were likely similar), `++` and `+=` were natural representations for `INC` and `ADD`. Whereas in assembler you'd write `MOV X, Y; ADD X, Z` (`x = y; x += z;` in C), C allowed you to write `x = y + z`. The fact that `x += 1` and `x++` are equivalent in the semantics of C doesn't change that fact that `INC X` was cheaper in several ways than `ADD X, 1`.  
---
## 9 answers
### Answer by username_19 on 2023-07-08. Score: 18
While `x += 1` may be replaced by ++x, x++ is special in that it is essentially `temp = x, x += 1, temp`. I am making a C-like which is an evolution of C, so removing x++ was never even something I considered, but I will also say that I prefer to have `++x` and `x += 1` because they *communicate different things* in the code if both are available in the language.

`++x` tells me: "increment to the next value". That is, we're iterating over something. This might be walking through an array or looking at every value in a range. But it is not making any jumps or anything.

`x += 1` on the other hand is saying "increase x by one", so this could be to adjust something by one, or jumping some amount, which just happened to be `1` but could just as well have been 2 or 5. Typically I would assume this means we're not using x to iterate (when ++ and -- exists in the language), and x += 1 is that hint.

That said, they are conveniences and can be dropped. Going as far as saying they're "actively harmful" like Swift does, seems like a very extreme opinion.
> **Comments:**
> **username_20** (2023-07-08): Yes, I've always been bothered by the use of `x++` when `++x` is appropriate. I know modern compilers will generate the same code, but my ancient brain still sees it as `(temp = x, x += 1, temp)`.  
> **username_21** (2023-07-08): @RayButterworth Hey, it sounds better like that ngl (my brain is probably not as ancient).  
> **username_22** (2023-07-08): @Ray  Modern compilers cannot generate the same code for each. For the actual increment or decrement, maybe. But the difference is that the ++a uses the new value immediately, wheras a++ continues to use the old value. The distinction is only resolved at the next "sequence point" (typically end of statement), which opens the door to a hatful of UB.  
> **username_19** (2023-07-09): If you look at it in SSA form the code will be pretty much identical, showing how the old value of x can easily be kept in a register. If you have `int b = a++`, then it's also possible to think of that as `int b = a; a += 1;`. The lack of sequence points is just by definition in C. A language can easily decide UB due to ++ and -- well defined.  
> **username_23** (2023-07-10): @Paul_Pedant they can generate the same code in cases where the value isn't observed until *after* that sequence-point, which is true in the (extremely) common case where `x++` is a statement on its own.  
> **username_24** (2023-07-10): `++x` _shouldn't_ tell you "increment to the next value", if `x` is a floating-point type...  
> **username_5** (2023-07-10): @Nuoji I don't know Swift well, but looking at the assignment operator in the language reference, it looks like the assignment "operator" is really a statement (in that an assignment has no value of its own), and from that standpoint an *expression* that has both a value and a side effect is something that modern languages tend to frown upon.  
> **username_19** (2023-07-11): @chepner you just described almost every procedure call in imperative and OO languages. I don't think that is a valid point.  
> **username_5** (2023-07-11): There's a difference between a function/procedure call that returns a value (even if it's a trivial value like `void`, `()`, `None`, etc) and something like a `for` statement that has no conceptual value at all.  
---
### Answer by username_15 on 2023-07-07. Score: 14
C isn't a language that comes with fancy iteration constructs like `foreach` or `map`. This means programmers need to increment something *every time* they loop over indices of an array or a string, or over pointers.

Making `i++` a shorthand for `i += 1` makes a little more sense when you're going to spend so much time writing `for (int i = 0; i < n; i++)` or `for (p = s; *p; p++)` all over again.

Maybe more interestingly, even though `+=` is more general and more powerful than `++`, **more power might be bad**. Having increment be distinct from compound assignment means you are encouraged to think at a different level of abstraction.

You're not "using the full power of addition", you're just *doing the loop thing*.

You don't need to visually slow down to verify that you're actually adding the digit `1` instead of a lowercase `l` that crept in here, you're just *doing the loop thing*.

To make this point clearer, I could make a parallel with `while` being a distinct, less powerful version of `goto` (remember: more expressive power isn't necessarily a good thing). Reading a `goto` instills fear in me, and makes me read the entire function again because otherwise I might miss some subtle control flow possibility. Reading a `while` is just reading a regular, well-known and well-delimited local construct.

In a way, it is the same for `++`. (And for equivalents in other languages, like `inc` in Pascal/Delphi.)
> **Comments:**
> **username_25** (2023-07-07): I would disagree. I've had to write loops with `i += 2`, or 4, or 8 rather than 1 enough times that it doesn't bother me when I see a for loop written that way. Heck, I've even sometimes seen those desugared into while loops, and the overall result is just as readable.  
> **username_15** (2023-07-08): I don't think loops with `+=` are less readable at all. I'm saying it's harder to *confuse* a `++` loop with a `+=` loop.  
---
### Answer by username_9 on 2023-07-07. Score: 12
The `++` and `--` operators aren't really necessary. There are languages that get along just fine with `x += 1` and `x -= 1`. Like Python, or Swift (which *had* these operators [but *removed* them for being error-prone](https://github.com/apple/swift-evolution/blob/main/proposals/0004-remove-pre-post-inc-decrement.md)).

But because incrementing or decrementing a variable by 1 is extremely common (especially in a `for` loop), and because PDP-11 assembly language happened to make it easy to implement those operations, C's designers decided to provide `++` and `--` as syntactic sugar. And then a bunch of other languages decided to adopt the C syntax for their operators.
> **Comments:**
> **username_6** (2023-07-08): This strikes me as a huge facepalm ‍♂️ for swift. Their reasoning seems unsound given that they acknlowedge both the difference between statements and expressions (one returns a value) and the difference between pre and post increment. Perhaps there is some context in how people tend to write swift code.  
> **username_10** (2023-07-08): I couldn't disagree more with Swift's decision, but +1 for this as an answer to the question asked.  
> **username_9** (2023-07-08): @BruceAdams: Yeah, I'm not experienced with Swift, but the decision seems weird.  They could have just changed the return value of the operators to `Void`, which would still allow `x++` and `x--` as standalone statements, while avoiding confusing uses like `f(++x, x++)`.  
> **username_11** (2023-07-08): @dan04 What would be the point of having `x++` and `++x` if they wouldn't return anything? The only difference between them is what they return.  
> **username_9** (2023-07-08): @xigoi: Just backwards compatibility.  Both `x++` and `++x` would become redundant ways of spelling `x += 1` as a standalone statement.  
> **username_12** (2023-07-09): The reference given doesn't support that Swift removed those operators because they'd be "error prone".  They are giving mostly different reasons for their decision in the reference.  
> **username_13** (2023-07-09): Operator `--` is useful to implement `while (u-- > 0) {...}` where u is an unsigned.  The "equivalent" `while (u -= 1 >= 0) {...}` would results in an infinite loop.  
> **username_14** (2023-07-09): Rust is another example that has `+=` but not `++`.  
> **username_7** (2023-07-10): @dan04 removing an operator altogether _is_ the safest option. It guarantees that anybody compiling a piece of code containing the operator sees a clear and to the point error message, which will be easy to fix. Only changing the type bears the risk of confusion. Shouldn't really be a problem for something as simple as `++`, but on the other hand this is also the kind of thing that already first-week beginners will be exposed with, and they might struggle.  
---
### Answer by username_15 on 2023-07-08. Score: 11
(Yes, I'm writing another answer to this question.)
Sometimes i++ really is what you need.
Here's an example where it shines. Consider the following code fragment:
int index = 0;
Set(index++, "Draw");
Set(index++, GetDistance());
Set(index++, GetColor());
Set(index++, GetOptions());

How would you write that in a language that doesn't have, specifically, the postfix increment operator?

You could use constants:
Set(0, "Draw");
Set(1, GetDistance());
Set(2, GetColor());
Set(3, GetOptions());

But this is error prone! If you ever need to reorder these lines, or to insert another line, or to delete one of those lines, it's easy to forget updating the index constants.

You could use compound assignment:
int index = 0;
Set(index, "Draw");
index += 1;
Set(index, GetDistance());
index += 1;
Set(index, GetColor());
index += 1;
Set(index, GetOptions());
index += 1;

But this is twice as many lines of code! And the alternation of lines isn't as easy to inspect... We make this look better:
int index = 0;
Set(index, "Draw"); index += 1;
Set(index, GetDistance()); index += 1;
Set(index, GetColor()); index += 1;
Set(index, GetOptions()); index += 1;

But now the code is unaligned, again it is not easy to verify that the repeated part is correctly done and no index += 1 was forgotten (imagine longer lines). We can do better by moving the similar part towards the beginning of the line:
int index = -1;
index += 1; Set(index, "Draw");
index += 1; Set(index, GetDistance());
index += 1; Set(index, GetColor());
index += 1; Set(index, GetOptions());

Now the code is compact and easy to verify again... But the index starts at -1, that's weird!

You could introduce a separate function:
int ReturnAndInc(int &i) { *i += 1; return *i; }
[...]
int index = 0;
Set(ReturnAndInc(&index), "Draw");
Set(ReturnAndInc(&index), GetDistance());
Set(ReturnAndInc(&index), GetColor());
Set(ReturnAndInc(&index), GetOptions());

Now this is good! Code is compact, it's easy to insert/delete/update lines, it's easy to verify that the index is good!
But we basically reimplemented i++.

Looks like sometimes ++ is useful after all. Now, this doesn't mean it needs to be built-into the language! The last solution can be acceptable, even more so if it can inline ReturnAndInc.
> **Comments:**
> **username_15** (2023-07-08): You could also have the helper function do both the increment and the call to Set... But what if Set has overloads? Now you need to make many similar helper functions, kept in sync with the number of overloads... I didn't want to include that case in the answer.  
> **username_6** (2023-07-08): Yuck. Modern language design includes elements of adding syntactic sugar to remove boilerplate. Removing it for something so common seems wrong.  
> **username_16** (2023-07-08): You could use `i = -1; Set(i += 1, "Draw"); Set(i += 1, GetDistance()); etc.` too, but that's also a bit awkward and then not everyone likes using (compound) assignments as expressions. Then again, why doesn't your `Set()` thingy have an append-like function that would keep track of the last used / first free index?  
> **username_15** (2023-07-08): Swift, in which `++` was removed, also decided to have `+=` return void... And making a `Set()` that also increments the index is boilerplate work that might not always pay for itself, compared to sprinkling some `++`.  
> **username_17** (2023-07-08): Honestly I think the version that uses the constants is the most clear one. If you have a lot of these you can just iterate an integer range instead of mutating a variable.  
> **username_15** (2023-07-08): Personal experience: I've tried using the constants. I've had to fix the resulting bugs.  
> **username_18** (2023-07-09): @Aiono As soon as you're doing it an unknown number of times tho, such as in a loop, that falls apart. Or if `index` starts at an unknown value.  
> **username_7** (2023-07-10): "You could also have the helper function do both the increment and the call to Set" - well you _should_! `template<typename... A> set_incr(index, A... args) {set(index, args...); index+=1;}` or something like that. Ok, many languages don't have variadic templates, but most nowadays have at least some form of parametric polymorphism, that should be enough. Alternatively: this really looks like something that should happen in a [state monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)#State_monads).  
> **username_15** (2023-07-10): You could do that... What if some of the `Set()` are actually `SetDifferently()`? You could add more boilerplate... Or type `++`.  
---
### Answer by username_27 on 2023-07-08. Score: 7
In many cases, `++` and `--` are used to move to the "next" thing or the "previous" thing. Although this is equivalent to adding 1, the essential concept embodied in the operation is "next" or "previous", and not "1".(\*)

The situation is somewhat analogous to the way many languages allow a programmer to write `if (flags & BITMASK) ...` rather than `if ((flags & BITMASK) != 0)`. One might describe the former operation as "is the set of bits in common between the two values non-empty" and the latter as "is the set of bits of values equal to something other than the empty set".

IMHO, good languages should avoid requiring programmers to write "phony constants". If there's only one constant value that has a certain property, having a construct that embodies that property is cleaner than requiring that programmers specify the explicit construct.

(\*) This becomes especially true if one views bytes of memory as being located *between* addresses, but with the convention that a single address will by default refer to the immediately following storage. Under this view, a 16-byte region of memory will have 17 addresses, with all but the last each uniquely pointing to the start of a byte, and all but the first each uniquely point to the end of a byte.

Viewing memory in this fashion, "incrementing" a pointer means that it should be made to identify an object that starts where the current object ends, and "decrementing" a pointer means it should be made to identify an object that ends where the current object starts. Note that in this scenario, there would be no space between the previously and newly identified objects.
---
### Answer by username_26 on 2023-07-08. Score: 5
Why add an increment/decrement operator when compound assignnments exist?

Why add compound assignment when regular assignment exists? After all, in C, x += 1 is equivalent to x = x + 1. Going further, there are many things that look redundant: why have all three of do..while, while and for? Why have loops to begin with if you can use goto or recursion instead? Why do CPUs have all these instructions when x86's mov instruction is Turing complete?
Languages are created to make programming more easy, but you also have to remember that you need to be able to create an interpreter and/or compiler for it. It's easy to forget that when K&R released their first specification of C, most consumer computers were still using 8-bit processors, and 64 kiB of RAM was considered a large amount. The PDP-11 that C was developed on was a 16-bit computer which could be made to support up to 4 MiB of RAM, but programs were still limited to a 16-bit address space. So compilers couldn't be very fancy.
As dan04 already mentioned, the PDP-11 had pre- and post-increment operations in its instruction set. So having increment/decrement operators in the language that are easy to parse and easy to generate instructions for makes a lot of sense. Also, consider that incrementing by one is an extremely common operation (already mentioned in several other answers), so it makes programming in C more easy. Consider this string copy function, which is just a one-liner when using post-increment on the pointers:
void strcpy(char *dst, const char *src) {
    while((*dst++ = *src++));
}

Some people object to this because they find it hard to follow. What if I write:
x = f(x++, x++);

Even if it's well-defined it's hard to tell what this does without knowing exactly what the rules are for the ordering of operations here. It's worse if it's implementation-defined what will happen. That's an argument against these operators.
> **Comments:**
> **username_11** (2023-07-08): `x += 1` is not necessarily equivalent to `x = x + 1` if you substitute a more complex expression for `x`, such as `arr[rand() % arr_len]`.  
> **username_26** (2023-07-08): @xigoi True, but you can easily work around that without needing compound assignment. My point is that a lot of things in languages are not really necessary, even if they are very convenient.  
---
### Answer by username_25 on 2023-07-07. Score: 4
C had those operators because C was designed to mirror the assembly of the particular machine it was developed for. Some modern languages have no such operator -- Swift in particular cited that `++` and `--` were "actively harmful".
> **Comments:**
> **username_20** (2023-07-08): It wasn't exactly designed for the purpose of mirroring the machine language; it was designed to take advantage of it. Compiling `++x` trivially generated a single instruction. Compiling `x+=1` would require testing for the 1 value in order to decide to handle that special case, which would make the compile take longer. (And yes, compilers really were very slow, so any time saving was worth it.)  
---
### Answer by username_6 on 2023-07-08. Score: 2
There are some important semantic differences between increment and decrement operators vs the addition and subtraction assignment operators.
Consider an iterator walking some kind of data structure like an array vs an expensive generator function.
It may not be possible to jump to the Nth element without computing the intermediate elements first.
So while:
iter += 3

is equivalent to:
iter.next().next().next()

and indeed you can construct the whole of arithmetic this way, it is not necessarily efficient.
Defining a additional assignment operator can be used to imply that there is a short cut.
In some languages it is useful to imply the computational cost but not defining additional assignment if it is not efficient.
So for a number type you can easily do:
 x = 1;
 x += 5;  // what it looks like - just a simple addition operator

It would seem less intuitive to write:
 class iterator
 {
     calculate_next();
     opeator++() { calculate_next(); }
 };

 foo++   // fine as alias for calculate_next;
 foo+=5  // less obvious as an alias for calculate_next repeated 5 times;

There is potentially a loop in the second case which does not exist in the first case. Though it gives the right answer, Peano arithmetic is not computationally efficient.
Another difference is that increment and decrement tend to be usable as expressions while addition assignment tends to useable only as a statement.
 x+=2

is more intuitive than:
 y=(x+=2)

If used as an expression it would also be a pre-increment whereas x++ is a post increment.
With increment and decrement operators (in C and C++ at least) you can define whether the value is incremented before or after the return.
That is in the context of:
 y=++x;

 ++x    

means:
 x=x+1;
 return x;

Whereas in the context of:
 z=x++;

 x++

means:
 ret=x;
 x=x+1;
 return ret;

Thus:
 y > z

All this is true even without considering the historical origins of increment and decrement in relation to C as a layer on top of assembly languages which may themselves have distinct increment and addition operations.
> **Comments:**
> **username_7** (2023-07-10): This is the most compelling reason, IMO.  
---
### Answer by username_8 on 2023-07-08. Score: 2
There are some good long answers. The short one is that it makes working with arrays and other containers with dense index-based access easier, shorter and less error prone. You can easily misstype 2 instead of 1.
---
