6

My doubt is about the usage of Increment/Decrement Operators (++ and --) in C (Also in C++). Is it absolutely necessary to use ++ and -- in programs? For example consider the code given below,

int x=10;
x++; 

This can be easily replaced as follows,

int x=10;
x=x+1;

So is it necessary to use ++ and -- in practical programming? I am asking this for a particular reason. In my opinion they are one of the most confusing operators in C, forming expressions like *x++, ++*x, x++ + ++x etc. and causing thousands of errors each day.

Of course I know that a direct mapping between ++ and the Assembly Instruction INCR is possible. But I believe any decent compiler with some ability to optimize can replace x=x+1 with INCR x.

So in short my Question is "Is there any situation where x=x+1 can not replace x++ ?".

It might be very helpful if somebody can provide a piece of code which will not work in the absence of ++ or --.

Any suggestions? Thank You.

Deepu
  • 7,592
  • 4
  • 25
  • 47
  • @huseyintugrulbuyukisik what do you mean by "if the compiler does from left to right"? Compilers are irrelevant, this isn't implementation-defined. –  May 19 '13 at 13:31
  • 8
    How else would we have [the "down to" operator `-->`](http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator)? – rubenvb May 19 '13 at 13:32
  • 1
    I feel the opposite way. I believe increment/decrement operators *can* greatly improve the readability of code, but they should not be used to extremes. – Marc Claesen May 19 '13 at 13:33
  • 2
    I strongly doubt there is any case, but the same is true for array lookup syntax, most loops and conditionals, etc. so that's not a good criterion for whether it should be used, or put in the language to begin with. @huseyintugrulbuyukisik Adding to rightfold's point, `(x = x + 1)` is equivalent to `++x`, not to `x++` (assignment evaluates to the assigned value, so you get the *new* value of x. –  May 19 '13 at 13:33
  • What do you base your "thousands of errors each day" assertion? Anybody who programs in C or C-derived languages needs to be familiar with standard idioms like post- and pre-increment operations. – Paul Tomblin May 19 '13 at 13:35
  • @Paul Tomblin: I teach C programming at graduate level. There I have observed the phenomena of "thousands of errors each day" :) I was not thinking about actual programmers. – Deepu May 19 '13 at 13:45
  • Personally, I'd hate it if there weren't shorthand-forms for arithmetic operations. `x = x + 1` for increments is akin to using `goto` for loops. – eq- May 19 '13 at 13:45
  • your examples show abusive usage of `++`. the operator itself is actually not that bad, you don't have to type spaces. – yngccc May 19 '13 at 13:48
  • 6
    Without the increment operators, `C++` would have to be called "C = C + 1, C - 1" instead. And that's a mouthful. – Benjamin Lindley May 19 '13 at 13:51
  • @Benjamin Lindley: Post the comment as an answer I will definitely upvote it. :) – Deepu May 19 '13 at 13:53
  • Answers are closed, it seems: Answer: Yes, for every type of `x` that has `operator+(...)` and `operator++(int)` with differing semantics. – Eric Towers Dec 22 '15 at 22:14

7 Answers7

11

Is there any situation where x = x + 1 can not replace x++?

Sure, foo(x = x + 1) is different from foo(x++) because x = x + 1 yields the new value of x and x++ yields the old value of x.


Beyond that there's isn't much difference and strictly ++ and -- aren't needed (i.e. you can write all programs with x += 1 instead of ++x and x -= 1 instead of --x).

Note that in C++ operator++ and operator-- can be overloaded and are in particular useful when manipulating iterators.

  • That's what `++x` is for. – rubenvb May 19 '13 at 13:35
  • 1
    But of course, that's just a problem the *letter* of the question. It's trivial to split this up into two statements: `foo(x); x = x + 1;`. –  May 19 '13 at 13:37
  • @delnan, you got it the wrong way around. What you'd want to replace `f(x++)` is `f(x); x = x + 1`. – eq- May 19 '13 at 13:38
  • 4
    @eq- True. We're doing an awful job convincing OP that ++ and -- aren't as error prone as he claims ;-) –  May 19 '13 at 13:39
4

The main benefit of the shorthand operators (++, --, +=, -=, *=, etc) is that you don't need to repeat the operand. This is no big deal for

x = x + 1; 

It's pretty easy to see that x is the same variable as x. But what about:

ptr->kerflunk->var.arr[x+y+z*w+i] = ptr->kerflunk->var.arr[x+y+z*w+i] + 1;

how different is that from:

ptr->kerflunk->var.arr[x+y+z*w+i] = ptr->kerflunk->var.arr[x+y-z*w+i] + 1;

Where if you see:

ptr->kerflunk->var.arr[x+y+z*w+i]++;

In this latter case, it's very easy to see that's the same thing.

(And yes, I'm making an extreme example which may quite possibly be improved by using some temporary variables for some bits of the complex structure, etc - but the fact remains that the expression using ++ is much simpler to see "it increments this value")

I don't think C and C++ are good beginner languages - and it's perfectly fine to teach the early part of C and C++ without using ++, -- and +=, -=, etc. Just use x = x + 1.

[And of course, if you like to, you can still use C/C++ to mess things up and still be something that can validly compile: a[x = x + 1] = b[x = x + 1]; is syntactically valid, but will also produce the same problem as using x++ twice between two sequence points].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
3

Iterators.

x = x + 1 implies that any number can be added to x, which might not be the case for certain types of x.

In case of iterators.

Forward iterators can be only incremented, bidirectional iterators can be also decremented, but you can't add any number to them. From programmer's point of view it might enforce efficient container access, so you won't be tempted to use std::list::begin() + 65536 or something.

Random access iterator, on other hand, allow arithmetical operations on iterators.

--edit--

Is it absolutely necessary

No language feature is absolutely necessary.

In case of C++ you could get rid of stl, namespaces, classes, preprocessor, templates, local variables, exceptions and function calls and STILL produce working program that'll do something. Of course, this program will be mostly unreadable and it'll take longer to write it, but it is possible. Basically all you need to program is goto, arrays, global variables, function that'll read/write characters from/to terminal and that's it. Everything else is technically optional.

Language features are made to make your life easier, not because it is impossible to live without htme. As for ++/-- operators, they seems to be the most useful for implementing forward/bidirectional iterators and other data types that support prev/next semantics, but do not support increment/decrement by arbitrary argument.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • 1
    While the general idea of that restriction is good API design, it is independent of having dedicated operators for the individual operations. In a C++ based on C-without-increment/decrement-operators, the operation now implemented as increment may be spelt `it.next()` and the operation that's now decrement may be spelt `it.prev()`. –  May 19 '13 at 14:09
  • IMO, the only difference between `it.next()` and `it++` is function name and a bit of syntax sugar.Same applies to `x = x + 1` which is equivalent to `x = add(x, 1)`. – SigTerm May 19 '13 at 14:11
  • 1
    My point exactly. So how does your example show increment/decrement operators are *needed* (which is the question, for better or for worse)? –  May 19 '13 at 14:12
  • @delnan: You can live without pretty much every feature in C++. All you need to program is arrays, function calls, and few basic types. You cab get rid of templates, macros, stl, dynamic memory allocation, and still produce working program (although it'll take longer). No language feature is "needed", but they make life easier. Iterators fall into this category. – SigTerm May 19 '13 at 14:16
  • 1
    Can `x++` be replaced with `x=x+1` in all circumstances? No. This is the only answer that seems correct to me to the question at hand. The title of the question is clarified in the body. Increment and decriment are different types of operations than add-by-`int`, and you cannot replace increment with add-by-`int`. You could give it a new name, but a new name is not what the question asks about. – Yakk - Adam Nevraumont May 19 '13 at 14:19
  • @SigTerm There is a huge difference between iterator advancement being slightly wordier and throwing out 90% of the language (going back to the first version of Pascal, replacing loops and conditions with `goto`). But what you're pointing out is a valid complaint against the *question*. In fact, I agree and posted a similar complaint 51 minutes ago myself! But alas the question is as it is. –  May 19 '13 at 14:24
  • @delnan: In my opinion, using 2 (`++`/`--`) characters vs 7 (`.prev()`/`.next()`) is a big difference, especially on large body of code. The rest is syntax sugar. No offense, but I do not think that arguing about that is very interesting. I wrote this answer simply because **nobody** wrote anything significant about iterators, and they're used with `++`/`--` very frequently. – SigTerm May 19 '13 at 14:31
1

It seems highly doubtful that it's absolutely necessary -- there were a lot of programming languages (FORTRAN, COBOL, Pascal, PL/I, ALGOL, Simula, and many more) that didn't include any direct analog to C's pre-/post- increment/decrement operators.

That said, there is one fairly fundamental difference between ++x; or x++; and x = x + 1; -- the latter evaluates the operand twice, where the former evaluates the operand only once.

That would make a difference in the case of a macro where you're passing an argument that has side effects, and you only want those side effects to take place once, not twice. There aren't very many real examples of that though, because most obvious examples of an argument you only want to evaluate once (e.g., where the argument itself is something like x++) simply won't compile if you apply ++ to them (e.g., ++x++).

This is loosened slightly in C++ however, by the fact that (for example) a function can return a reference. Wanting to call the function only once, then increment the result it returns is at least a reasonable possibility. Yes, you could do that other ways (e.g., most C++ programmers would prefer an inline function to a macro) but it's at least a possibility.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

It absolutely isn't necessary..., but remember C isn't a computer language, it is a programming language, but still a human one... C gets thought of as a low level language, but there is still more than one possible output a compiler could produce from:

i++

it could store the value in a register, then increment, then copy back to the stack, decrement that register for the next statement that relies on i before the incr and use the same register for the next time it uses that value.

it could potentially in a CIS use one mnemonic to increment that on the stack.

it could make 2 copies one for incrementing and one for returning...

It doesn't matter as C has abstracted it away from you, but it sure makes code more readable.

Grady Player
  • 14,399
  • 2
  • 48
  • 76
0

For C++ this is more of efficiency than capability, assume you have object x of type X which is class type object

x = x + 1;

this involves (x+1) which adds 1 to x and returns a new copy of class X. Then this new temporary of X is copied to x. This can be done with out any copies with

++x;  

For C the only thing I can think of is convenience. If you use it right it is not confusing at all. Given the fact that single increments and decrements are essential parts of many algorithms it helps to make the intent clear and not confuse it with "normal" addition or subtraction.

stardust
  • 5,918
  • 1
  • 18
  • 20
  • Despite the C++ tag, the question mentions mostly C. Edit: Yeah, it mentions it off-hand once, but it clearly focuses on C. Some mention of C (and primitive types in C++) would be useful. –  May 19 '13 at 13:37
  • @delnan Are you really deciding on what OP meant for him? – stardust May 19 '13 at 13:40
  • Well, since the question is tagged C and this answer makes no sense for C, you could mention that it's for C++. That would not be deciding what the OP meant for him/her, that would be providing a clear answer. – Pascal Cuoq May 19 '13 at 13:42
  • @Named No. *I* meant that answers should address the other half of the question (the C part) too. You are right, my claim that the question is C-only was wrong. I've switched to complaining that it's not *only* C++ ;-) –  May 19 '13 at 13:42
  • @delnan Well the only thin I can think of for `C` is **convenience**. I didn't put it there because it didn't seem he was concerned with convenience. But right I should have mentioned it is for C++ only. – stardust May 19 '13 at 13:45
  • 1
    It's convenience for both. You could just write `+=` instead of the assignment. Even if you couldn't, with moves & optimizations it's wrong of you to say one is less efficient than the other. You can't just throw a statement like that without any benchmarking. – Luchian Grigore May 19 '13 at 13:49
0

The short answer is that x = x + 1 cannot always be directly substituted for x++ (in terms of a search-and-replace operation), but any occurrence of x++ can be replaced with equivalent code that does not use the increment operator.

As rightfold wrote, a call to f(x = x + 1) passes the incremented value of x, while a call to f(x++) does not; but you can easily fix this with f(x); x = x + 1;.
You can even use x = (f(x), x + 1);, though this is arguably harder to read.

The increment operator makes it easy to assign and increment a value in a single line, but you can choose whether the increment occurs before or after the value is used:

x = 1;
y = ++x;  // y = 2, x = 2
z = x++;  // z = 2, x = 3

With a simple assignment like x = x + 1 the value is always used after the increment occurs.

It's particularly useful in pointer operations. For example, you can copy a null-terminated string very concisely:

while ((*dest++ = *src++) != '\0')
  ;

This is a very common idiom, and experienced programmers will recognize and understand it immediately. So it's a very convenient shorthand, but you can always expand the code:

while (true) {
  *dest = *src;
  if (*dest == '\0') {
    break;
  }
  src + src + 1;
  dest + dest + 1;
}

Although this gives the same result, it takes much more effort to read and understand. In fact, I'd expect an experienced programmer to wonder why the author didn't just use the simpler version -- was it inexperience, or is there some hidden difference?

Adam Liss
  • 47,594
  • 12
  • 108
  • 150
  • Whether code like `while (*dest++ = *src++);` is good code is very arguable. I am perfectly comfortable with pointers and post-increment, but I need a double-take for such code. I've heard other people criticize it as well. Besides, how often do you write code like that? It's longer and slower than `strcpy`. –  May 19 '13 at 13:49
  • I'd argue that it's _not_ good code: a semicolon on the same line as a loop statement can easily be overlooked by a reader, misleading them into thinking the code below will be executed multiple times. But other than that, the idiom is common enough among professionals that I think you're in the minority. I think the shorter form is far more readable than the longer, and that's supported by my colleagues and our coding standards. – Adam Liss May 19 '13 at 13:53
  • 1
    "You can even use `x = f(x), x + 1;`" should probably be "You can even use `x = (f(x), x + 1);`". The comma operator has lower precedence than assignment. – Daniel Fischer May 19 '13 at 14:36
  • Yes, absolutely, @DanielFischer. Fixed - thank you. – Adam Liss May 19 '13 at 23:51