Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Recently, I've stumbled across question about predicting the output of code which heavily uses post/pre increment operators on integers. I am experienced C programmer, so I felt like at home, but people made statements that Java just blindly copied that from C (or C++), and that this is an useless feature in Java.

That being said, I am not able to find good reason for that (especially with keeping in mind the difference betwen post/pre forms) in Java (or C#), because it's not like you will manipulate arrays and use them as strings in Java. Also, it was long ago when I last looked into bytecode, so I don't know if there's a INC operation, but I don't see any reason why this

for(int i = 0; i < n; i += 1)

could be less effective than

for(int i = 0; i < n; i++)

Is there any particular part of the language where this is really useful, or is this just a feature to bring C programmers in town?

share|improve this question
2  
"Gosling wanted the code written by someone experienced in C (not in Java) to be executed by someone used to running PostScript on NeWS..." –  gnat Mar 24 at 11:52
7  
@TimothyGroote I don't think that's a fair assessment since 1) arrays are mutable, Strings aren't; 2) you can't assign a String to a char[] or vice-versa. They're certainly array-like, they're likely implemented with arrays, and it's easy enough to convert to and from an array, but they're definitely not the same thing. –  Doval Mar 24 at 11:54
3  
Lots of good answers here so I won't re-state what others have already said, except to emphasize that these operators are horrid features. They're very confusing; after over 25 years I still get pre- and post- semantics mixed up. They encourage bad habits like combining evaluation of results with production of side effects. Had these features not been in C/C++/Java/JavaScript/etc, they would not have been invented for C#. –  Eric Lippert Mar 24 at 20:39
5  
To respond directly to the claims made by your people: C# did not blindly copy anything from anyone. Every feature of C# was extremely carefully designed. And these are not useless features; they have a use. –  Eric Lippert Mar 24 at 21:08
2  
@EricLippert: I think (hope) most of us can agree that pre/post increment are awful, but in that context... why were they included in C#? For familiarity's sake? –  Phoshi Mar 25 at 10:56

4 Answers 4

up vote 16 down vote accepted

is this just a feature to bring C programmers in town

It is surely a feature "to bring C (or C++) programmers in town", but using the word "just" here underestimates the value of such a similarity.

  • it makes code (or at least code snippets) easier to port from C (or C++) to Java or C#

  • i++ is less to type than i += 1, and x[i++]=0; is much more idiomatic than x[i]=0;i+=1;

And yes, code which heavily uses post/pre increment operators maybe hard to read and maintain, but for any code where these operators are misused, I would not expect a drastic increase in code quality even when the language would not provide these operators. That's because if you have devs which don't care for maintainability, they will always find ways to write hard-to-understand code.

Related: Is there any difference between the Java and C++ operators? From this answer one can deduce that any well-defined operator behaviour in C is similar in Java, and Java does only add some definitions for operator precedence where C has undefined behaviour. This does not look like coincidence, it seems to be pretty intentional.

share|improve this answer
9  
"if you have devs which don't care for maintainability, they will always find ways to write hard-to-understand code" - very well said –  Don L. Mar 24 at 12:53
    
Do you subscribe to the common belief among C programmers that you only have so many C keystrokes in you before you die? Saving that one keystroke seems like a poor tradeoff to me. –  Eric Lippert Mar 24 at 20:41
    
@EricLippert: hello Eric, as one of the creators of C# why don't you enlighten us and tell us a little bit about your motivation to keep the operators in C# similar to Java and C? –  Doc Brown Mar 24 at 20:53
    
@DocBrown: Your answer applies pretty well to C#. I left a comment above. –  Eric Lippert Mar 24 at 20:54
1  
@DocBrown: x[i++]=0 is idiomatic in C, but I disagree that it's idiomatic in C# and Java. How often you encounter such phrases, unless you work in engineering/mathematics domain, which, I presume, consitutes no more than 1% of Java/C# code in the wild? –  Mladen Jablanović Mar 27 at 9:38

I use sometimes the postfix increment in return statements. E.g. consider this:

//Java
public class ArrayIterator implements Iterator<T> {
   private final T[] array;
   private int index = 0; 
   public ArrayIterator(T ... array) {
      this.array = array;
   }

   public T next {
      if (! hasNext()) throw new NoSuchElementException();
      return array[index++];   
   }
   ...
}

You can't do this with index += 1. So at least the postfix version can save you now and then some lines.

That said, these operators are indeed not necessary, and may confuse people. I know Scala decided against these operators (you have only += and -=, as you suggested), and due to the more "high-level" approach I don't really miss them there. I hope Java develops (more slowly) in the same direction.

However Java has a bunch of other operators you don't see very often "in the wild" (did you ever use ^= or >>>= ?), and nobody cares.

share|improve this answer
1  
^= is a reasonably common one. You can use it for flipping bitfield flags, swapping two integers without a temporary variable, and in some hash/cipher algorithms. I admit that I've never used >>>=, though. (Then again, I've never used >>> or <<< in any production program...) –  Brian S Mar 24 at 21:40

I've built many languages over the years, mostly special-purpose. What happens is you have a large audience, and they all have expectations. In considering each feature, you have to weigh the benefit of the feature against the cost of possibly violating expectations.

One that I personally had to backpedal on was integer division, which normally truncates downward, right? Like 3 / 2 = 1.5 = 1, right? Well, way back in the early days of Fortran, somebody decided -3 / 2 = -1.5 = -1 (not -2). In other words, if the dividend is negative and the divisor is positive, it should truncate up. Note what this implies - in that case the remainder is negative. That violates the usual assumption that remainder = modulus. If you're doing graphics, with integer coordinates, this can lead to all kinds of trouble. SO, in the language I simply had integer division truncate downward all the time, and say so in the doc.

And SO, guess what happened? All h*** broke loose. The language had a bug in integer division!

It did no good to say the old way was broken. It was easier to change it than to argue it.

So to answer your question, in languages like C# and Java, it's simply easier to include the ++ operators (which I personally like) than to explain why not.

share|improve this answer
4  
As another example, the D programming language (which is in many ways the next evolutionary step from C++) has a switch statement, and they kept the required breaks in each clause even though the language doesn't allow falling through. While D threw away C++'s backwards compatibility with C, their policy is that any C construct that D kept should surprise a C programmer as little as possible. –  Doval Mar 24 at 13:07
    
@Doval: I even built a language I called D, like C but with OO and parallelism features. It went nowhere (mercifully) and has no relation to the D you are talking about. I drive people crazy in C?? by always writing break; case ... ;-) –  Mike Dunlavey Mar 24 at 13:16
1  
@MikeDunlavey: My preference would be to say that / yields double or float (using double in cases where either would work), and have separate operators for floored, truncated, and "do whatever" division, as well as modulus, remainder, and "evenly divisible by" [the latter yielding a Boolean]. I would posit that any result of int x=y/z; has a significant likelihood of differing from what was intended, so therefore the expression shouldn't yield any result. –  supercat Mar 24 at 19:40
    
It's not uncommon in languages to have separate operators for int-divide-by-int yielding int or floating point. Also, the sign of the remainder (affects the quotient) varies wildly. See en.wikipedia.org/wiki/Modulo_operation for a list of languages. Part of the decision for FORTRAN was undoubtedly based on what the hardware they used (IBM pre-360?) and how it behaved with signed dividend and/or divisor. –  Phil Perry Mar 24 at 19:52
    
I know both Pascal and Python separate out the "yielding int" from "yielding floating-point" operators, though I've not seen any which separate out the rounding modes. I find it really icky that code which wants to e.g. compute the average of three numbers and could in Python be written as (a+b+c)//3 must in most languages be written as some obnoxious mess in order to deal with truncated-division semantics (especially since, on many processors, a floored-divide-by-three could be done faster than a truncated one!) –  supercat Mar 24 at 20:36

Yup, its nothing important in itself, its only benefit is the syntactic sugar that makes it easier to type.

The reason it is in C in the first place is solely because the PDP-11 that was the basis for C, way back in the old days, had a special instruction for incrementing by 1. In those days, using this instruction was important to get more speed out of the system, hence the language feature.

However, I think people like the command so much they would complain if it wasn't there.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.