The need for prefix and postfix

What is the need for prefix and postfix increment operators? Is it not enough?

At the same time, there is a similar while / do-while problem, but there is not much confusion (in understanding and use) if both of them exist. But it has both a prefix and a postfix (as the priority of these operators, their connection, use, work). And someone did a situation where you said: โ€œHey, I will use postfix increment. This is useful here.โ€

+6
source share
8 answers

POSTFIX and PREFIX do not match. POSTFIX increases / decreases only after completion of the current instruction / instruction. While PREFIX increases / decreases, and then performs the current step. Example. To start the loop n times,

while(n--) { } 

works great. But,

 while(--n) { } 

will only work n-1 times

Or, for example:

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

Point suppose that if there is only post -- , then we must write x = --n in two stages.

There may be other other reasons, but this is one of those that I intend to use for both the prefix and the postfix operator.

+5
source

[edit to answer the first part of OP]

It is clear that i++ and ++i affect i same way, but return different values. Operations are different . Thus, many codes make use of these differences.

The most obvious need to have both operators is the 40-year-old code base for C. When a language function is used widely, it is very difficult to delete.

Of course, a new language can only be defined with or without one. But will he play in Peoria? We could get rid of the - operator, just use a + -b , but I think this is a difficult sale.

Do you need both?

The prefix operator is easy to imitate the alternative code for ++i pretty much matches i += 1 . Unlike the priority of the operator that the parsers decide, I see no difference.

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

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

Fast Forward: โ†’ and <operators were assigned in C ++ to do something completely different from integer bit offsets. Maybe ++ pre and post ++ generate an extended value in another language.

[Original follows]

Answer the final OP question "did someone go through the situation when you said" Hi, I will use the postfix increment. Its useful here ??

Processing various arrays, for example using char [], is beneficial. Indexing an array starting at 0 is incremented by postfix. For after extracting / setting an array element, the only thing to do with the index before the next access to the array is to increase the index. Could do it right away.

When incrementing the prefix, one selection type for the 0th element and another selection type for the rest may be required.

 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'; 
+3
source

I believe that the only fair answer to what needs to be saved would be to destroy both of them.

If, for example, you had to do away with postfix operators, then when the code was once compactly expressed using n++ , you will now need to refer to (++n - 1) , otherwise you will have to rebuild other terms.

If you violated the increment or decrement on your own line before or after the expression that referred to n above, then itโ€™s not very relevant what you use, but in this case you can just as easily use none, and replace this line with n = n + 1;

So perhaps the real problem here is expressions with side effects. If you like compact code, you will see that both pre and post are needed for different situations. Otherwise, there does not seem to be much point in preserving them.

An example of using each of them:

 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++; 
+1
source

They are necessary because they are already used in a large amount of code, so if they were deleted, many codes were not compiled.

As for why they ever existed, 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 usually not a problem.

The postfix version is something like an anomaly, since nowhere in C is there an operator that modifies its operand, but evaluates the previous value of its operand.

It could be obtained using only one or more operators of incrementing a prefix or postfix. It would be a little harder to get only one or the other of the while or do while , since the difference between them is greater than the difference between the increment of the prefix and postfix in my view.

And you can, of course, do without using the prefix or postfix increment, or while or do while . But where do you draw the line between what is useless and what is a useful abstraction?

+1
source

Here is an example quickie that uses both; stack-based array, where the stack grows in the 0 direction:

 #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 can do the same without the ++ and - operators, but it will not scan as cleanly.

+1
source

As for any other obscure mechanism in C, there are various historical reasons for it. In ancient times, when dinosaurs walked the earth, compilers would make more efficient code from i++ than i+=1 . In some cases, compilers will generate less efficient code for i++ than for ++i , because i++ needs to be saved for further increase. Unless you have a dinosaur compiler, none of this matters in terms of efficiency.

As with any other obscure mechanism in C, if it exists, people will start using it. I will use the generic *p++ expression as an example (this means: p is a pointer, take the contents of p , use this as the result of the expression, and then increase the pointer). He must use a postfix and never a prefix, otherwise it will mean something completely different.

Some dinosaurs once began to write unnecessary complex expressions, such as *p++ , and because they did this, it became commonplace, and today we consider such code as something trivial. Not because it is, but because we are so used to reading it.

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

 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 of the popular ways to implement actual copying is:

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

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

I donโ€™t think any case is very readable, you have to be an experienced C programmer to understand it without scratching your head for five minutes. And you can write the same code like this:

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

For longer, and most importantly, it gives exactly the same machine code as the first example.

Now let's see what happened: because we decided not to write obscure code with a large number of operands in one expression, we could also use ++p1 and ++p2 . This will give the same machine code. The prefix or postfix does not matter. But in the first example with obscure code *++p1 = *++p2 completely change the meaning.

Summarizing:

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

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

+1
source

The prefix operator first increments the value, then uses it in the expression. Postfix, first uses the value in the expression and increments the value

The main use of prefix / postfix operators - assembler replaces it with a single increment / decment statement. If we use arithmetic operators instead of increment or decrement operators, the assembler replaces it with two or three instructions. therefore we use increment / decment operators.

0
source

You do not need both.

It is useful for implementing a stack, so it exists in some machine languages. From there, it was inherited indirectly to C (in which this redundancy is still somewhat useful, and some C programmers seem to like the idea of โ€‹โ€‹combining two unrelated operations in one expression), and from C to any other C-like closures.

0
source

Source: https://habr.com/ru/post/948565/


All Articles