I missed the fact that this question was about C instead of C#. This likely invalidates my performance argument, so I removed that part of the answer. However, I do think that the readability argument (which is 90% of my answer) remains to be a relevant consideration.
You didn't really explain what the code does, and you really should have. We need the surrounding context to make sense of why each snippet is relevant.
However, if I can rely on the fact that whoever corrected your code is sure that the alternative works the same way, then I think I understand the scenario:
- You are incrementing
- You're trying to have
i increment from 0 up to
N, multiple times. E.g. if
N = 5, you want
0,1,2,3,4,0,1,2,3,4,... For the rest of the answer, I will refer to this behavior as "cyclical values".
The rest of the answer works under this assumption.
I agree with the corrected version.
The modulo operator is a fairly niche operator, compared to other C# operations. By that, I mean that when you encounter the modulo operator, you can almost immediately assume that you're dealing with cyclical values.
This cyclical behavior is exactly the case for you, so I do advocate the use of the modulo operator. It makes the cyclical nature of the algorithm easily discernible.
Distinguishing between the logical and the mathematical.
There are other cases where you can choose between a logical approach and a mathematical one. A simple example is
for (mathematical) and
for(int i = 0 ; i < myArray.Length; i++)
var item = myArray[i];
foreach(var item in myArray)
These two are functionally equivalent. However, more importantly, observe the intention of a
foreach: it is used to direct the logical flow, it's not used (by itself) for calculating and storing values.
In the majority of cases, I would advocate the use of a
foreach instead of a
for, because it is easier to read a logical approach when the intention of the code is to direct the logical flow.
for loops have their uses, e.g. when your iterations need a counter value to keep track of which iteration you're in. This is where the mathematical side of things becomes more important. But for the majority of use cases, you'll simply be iterating over an entire list and will not need a counter.
If you boil this down, you get to the following rule of thumb:
In cases where the mathematical and logical approaches are sufficiently equivalent (!) you should use the logical approach when you're directing the algorithm's logic, and you should use the mathematical approach when making calculations.
This closes the gap between the code and the intention of the code. The smaller the gap, the more readable the code will be.
The general idea here is that when you use a mathematical approach for a logical flow, then the developer needs to understand the mathematics to understand how the code will flow.
A sufficiently experienced developer will of course not get hindered by something he's familiar with, e.g. the simple
for that I used. But as the logic gets more and more complex, the mathematical approach will compromise more and more of the code readability, faster than the logical approach will.
Let's go back to comparing your two options:
if (i >= N)
i = 0;
i %= N;
Observe the intention of the code: You are trying to find the next value of
i. That is inherently a mathematical operation, and therefore warrants the use of a mathematical approach over a logical one.