The short answer is: You never need them!
The long answer is that the instruction sets of early micro-computers had features like that. Upon reading of a memory cell, you could post-increment or pre-decrement that cell when reading it. Such machine level features inspired the predecessors of C, from whence it found its way even into more recent languages.
To understand this, one must remember that RAM was extremely scarce in those days. When you have 64k addressable RAM for your program, you'll find it worth it to write very compact code. The machine architectures of those days reflected this need by providing extremely powerful instructions. Hence you could express code like:
s = s + a[j]
j = j + 1
with just one instruction, given that s
and j
were in a register.
Thus we have language features in C that allowed the compiler without much effort to generate efficient code line:
register int s = 0; // clr r5
s += a[j++]; // mov j+, r6 move j to r6 and increment j after
// add r5,a[r6]
The same goes for the short-cut operations like +=
, -=
, *=
etc.
They are
- A way to save typing
- A help for a compiler that had to fit in small RAM, and couldn't afford much optimizations
For example,
a[i] *= 5
which is short for
a[i] = a[i] * 5
in effect saves the compiler some form of common subexpression analysis.
And yet, all that language features, can always be replaced by equivalent, maybe a bit longer code that doesn't use them. Modern compilers should translate them to efficient code, just like the shorter forms.
So the bottom line and answer to your question: you don't need to look for cases where one needs to apply those operators. Such cases simply do not exits.