by Leon Rosenshein

++ / --

History Lesson

The ++ (and –) operator has been around for a long time. Like 50+ years. They’re functions with side effects. Prefix (increment the variable and return the new value) and postfix (return the value, then increment) versions. You see them in loops a lot. They’re syntactic sugar created so that programmers could write code with fewer keystrokes. But what’s that got to do with strings?

They’re syntactic sugar because back in the day, when the only data type you had was the WORD, and the only data structure you had was the VECTOR, you ended up with lots of code that looked something like

copy(from, to, count) {
  i = 0;
  while (i < count) {
    to[i] = from[i];
    i = i + 1;
  }
}

Add in pointers and the new operators, and it turns into

copy(from, to, count) {
  while (count--) {
    *to++ = *from++;
  }
}

5 lines instead of 7. No initialization. Less array access math. Smaller code. Faster code. And almost as readable.

But what has that got to do with strings? It’s related to strings, because, if you assume null terminated strings, and 0 == FALSE, that loop turns into

strcpy(from, to) {
  while (*to++ = *from++) ;
}

Simple. Efficient. 3 Lines. Minimal overhead. And the source of one of the biggest security nightmares, the buffer overflow. Add in multi-byte character sets and unicode and it gets even scarier.

But that’s not the only scary thing about ++/–. As I mentioned before, they’re functions, with side effects. All by themselves, without an assignment you’re just getting the side effect, incrementing/decrementing the variable. That’s pretty straightforward. When you start using the return value of the function, things get more interesting.

Consider this snippet

#include <stdio.h>
#include <stdlib.h>
int main() {
  int i;
  
  printf ("\ni = i + 1\n");
  i = 0;
  while (i < 100) {
      i = i + 1;
      if (i % 10 == 0) {
        printf ("%d is a multiple of 10\n", i);
      }
  }
  
  printf ("\n++i\n");
  i = 0;
  while (++i < 100) {
    if (i % 10 == 0) {
      printf ("%d is a multiple of 10\n", i);
    }
  }
  
  printf ("\ni++\n");
  i = 0;
  while (i++ < 100) {
    if (i % 10 == 0) {
      printf ("%d is a multiple of 10\n", i);
    }
  }
}

The three loops are almost identical, but the results are different for ++i and i++. Because all of a sudden your test, either ++i < 100 or i++ <; 100, has a side effect.

But at least now you know why you can shoot yourself in the foot like that. For more history on why things are the way they are, check out Dave Thomas