Karthik
Karthik

Reputation: 375

Prefix and postfix operators necessity

What is the necessity of both prefix and postfix increment operators? Is not one enough?

To the point, there exists like a similar while/do-while necessity problem, yet, there is not so much confusion (in understanding and usage) in having them both. But with having both prefix and postfix (like priority of these operators, their association, usage, working). And do anyone been through a situation where you said "Hey, I am going to use postfix increment. Its useful here."

Upvotes: 6

Views: 2760

Answers (8)

Lundin
Lundin

Reputation: 214495

As for any other obscure mechanism in the C language, there are various historical reasons for it. In ancient times when dinosaurs walked the earth, compilers would make more efficient code out of i++ than i+=1. In some cases, compilers would generate less efficient code for i++ than for ++i, because i++ needed to save away the value to increment later. Unless you have a dinosaur compiler, none of this matters the slightest in terms of efficiency.

As for any other obscure mechanism in the C language, if it exists, people will start to use it. I'll use the common expression *p++ as an example (it means: p is a pointer, take the contents of p, use that as the result of the expression, then increment the pointer). It must use postfix and never prefix, or it would mean something completely different.

Some dinosaur once started writing needlessly complex expressions such as the *p++ and because they did, it has became common and today we regard such code as something trivial. Not because it is, but because we are so used at reading it.

But in modern programming, there is absolutely no reason to ever write *p++. For example, if we look at the implementation of the memcpy function, which has these prerequisites:

void* memcpy (void* restrict s1, const void* restrict s2, size_t n)
{
  uint8_t* p1 = (uint8_t*)s1;
  const uint8_t* p2 = (const uint8_t*)s2;

Then one popular way to implement the actual copying is:

while(n--)
{
  *p1++ = *p2++;
}

Now some people will cheer, because we used so few lines of code. But few lines of code is not necessarily a measure of good code. Often it is the opposite: consider replacing it with a single line while(n--)*p1++=*p2++; and you see why this is true.

I don't think either case is very readable, you have to be a somewhat experienced C programmer to grasp it without scratching your head for five minutes. And you could write the same code like this:

while(n != 0)
{
  *p1 = *p2;

   p1++;
   p2++;  
   n--;
}

Far clearer, and most importantly it yields exactly the same machine code as the first example.

And now see what happened: because we decided not to write obscure code with lots of operands in one expression, we might as well have used ++p1 and ++p2. It would give the same machine code. Prefix or postfix does not matter. But in the first example with obscure code, *++p1 = *++p2 would have completely changed the meaning.

To sum it up:

  • There exist prefix and postfix increment operators for historical reasons.
  • In modern programming, having two different such operators is completely superfluous, unless you write obscure code with several operators in the same expression.
  • If you write obscure code, will find ways to motivate the use of both prefix and postfix. However, all such code can always be rewritten.

You can use this as a quality measure of your code: if you ever find yourself writing code where it matters whether you are using prefix or postfix, you are writing bad code. Stop it, rewrite the code.

Upvotes: 1

Aswin Murugesh
Aswin Murugesh

Reputation: 11070

POSTFIX and PREFIX are not the same. POSTFIX increments/decrements only after the current statement/instruction is over. Whereas PREFIX increments/decrements and then executes the current step. Example, To run a loop n times,

while(n--)
{ }

works perfectly. But,

while(--n)
{
}

will run only n-1 times

Or for example:

x = n--; different then x = --n; (in second form value of x and n will be same). Off-course we can do same thing with binary operator - in multiple steps.

Point is suppose if there is only post -- then we have to write x = --n in two steps.

There can be other better reasons, But this is one I suppose a benefit to keep both prefix and postfix operator.

Upvotes: 5

Elazar
Elazar

Reputation: 21645

You don't need both.

It is useful for implementing a stack, so it exists in some machine languages. From there it has been inherited indirectly to C (In which this redundancy is still somewhat useful, and some C programmers seems to like the idea of combining two unrelated operations in a single expression), and from C to any other C-like lagnuages.

Upvotes: 0

chux
chux

Reputation: 154075

[edit to answer OP's first part]

Clearly i++ and ++i both affect i the same but return different values. The operations are different. Thus much code takes advantage of these differences.

The most obvious need to have both operators is the 40 year code base for C. Once a feature in a language is used extensively, very difficult to remove.

Certainly a new language could be defined with only one or none. But will it play in Peoria? We could get rid of the - operator too, just use a + -b, but I think it is a tough sell.

Need both?

The prefix operator is easy to mimic with alternate code for ++i is pretty much the same as i += 1. Other than operator precedence, which parens solves, I see no difference.

The postfix operator is cumbersome to mimic - as in this failed attempt if(i++) vs. if(i += 1).

If C of the future moved to depreciate one of these, I suspect it would be to depreciate the prefix operator for its functionality, as discussed above, is easier to replace.

Forward looking thought: the >> and << operators were appropriated in C++ to do something quite different from integer bit shifting. Maybe the ++pre and post++ will generate expanded meaning in another language.

[Original follows]

Answer to the trailing OP question "do anyone been through a situation where you saidd "Hey, I am going to use postfix increment. Its useful here"?

Various array processing, like with char[], benefit. Array indexing, starting at 0, lends itself to a postfix increment. For after fetching/setting the array element, the only thing to do with the index before the next array access is to increment the index. Might as well do so immediately.

With prefix increment, one may need to have one type of fetch for the 0th element and another type of fetch for the rest.

size_t j = 0;

for (size_t i = 0, (ch = inbuffer[i]) != '\0'; i++) {
  if (condition(ch)) {
    outbuffer[j++] = ch;  // prefer this over below
  }
}
outbuffer[j] = '\0';

vs.

for (size_t i = 0, (ch = inbuffer[i]) != '\0'; ++i) {
  if (condition(ch)) {
    outbuffer[j] = ch;
    ++j;
  }
}
outbuffer[j] = '\0';

Upvotes: 3

John Bode
John Bode

Reputation: 123558

Here's a quickie example that uses both; an array-based stack, where the stack grows towards 0:

#define STACKSIZE ...

typedef ... T;

T stack[STACKSIZE];
size_t stackptr = STACKSIZE;

// push operation
if ( stackptr )
  stack[ --stackptr ] = value;  

// pop operation
if ( stackptr < STACKSIZE )
  value = stack[ stackptr++ ];

Now we could accomplish the exact same thing without the ++ and -- operators, but it wouldn't scan as cleanly.

Upvotes: 1

Oktalist
Oktalist

Reputation: 14714

They are necessary because they are already used in lots of code, so if they were removed then lots of code would fail to compile.

As to why they ever existed in the first place, older compilers could generate more efficient code for ++i and i++ than they could for i+=1 and (i+=1)-1. For newer compilers this is generally not an issue.

The postfix version is something of an anomaly, as nowhere else in C is there an operator that modifies its operand but evaluates to the prior value of its operand.

One could certainly get by using only one or other of prefix or postfix increment operators. It would be a little more difficult to get by using only one or other of while or do while, as the difference between them is greater than the difference between prefix and postfix increment in my view.

And one could of course get by without using either prefix or postfix increment, or while or do while. But where do you draw the line between what's needless cruft and what's useful abstraction?

Upvotes: 1

sh1
sh1

Reputation: 4751

I think the only fair answer to which one to keep would be to do away with them both.

If, for example, you were to do away with postfix operators, then where code was once compactly expressed using n++, you would now have to refer to (++n - 1), or you would have to rearrange other terms.

If you broke the increment or decrement out onto its own line before or after the expression which referred to n, above, then it's not really relevant which you use, but in that case you could just as easily use neither, and replace that line with n = n + 1;

So perhaps the real issue, here, is expressions with side effects. If you like compact code then you'll see that both pre and post are necessary for different situations. Otherwise there doesn't seem to be much point in keeping either of them.

Example usage of each:

char array[10];
char * const end = array + sizeof(array) / sizeof(*array);
char *p = end;
int i = 0;

/* set array to { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } */
while (p > array)
    *--p = i++;

p = array;
i = 0;
/* set array to { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } */
while (p < end)
    *p++ = i++;

Upvotes: 1

Chinna
Chinna

Reputation: 4002

Prefix operator first increments value then its uses in the expression. Postfix operator,first uses the value in the expression and increments the value

The basic use of prefix/postfix operators are assembler replaces it with single increment/decrement instruction. If we use arithmetic operators instead of increment or decrement operators, assembler replaces it with two or three instructions. that's why we use increment/decrement operators.

Upvotes: 0

Related Questions