Reputation: 1
Our codebase contains a few loops of the form while((*assignment*) *condition*)
, for example:
while((c = *s++) != '\0') {...}
while((i = getNext()) != NULL) {...}
Unfortunately these are causing the compiler to emit an "assignment in condition" warning, which I would like to get rid of. My plan is to transform the while
loops into for
loops of the form for(assignment; condition; assignment), for example:
for(c = *s++; c != '\0'; c = *s++) {...}
for(i = getNext(); i != 0; i = getNext()) {...}
Is this transformation valid? Is there a better alternative?
Upvotes: 0
Views: 266
Reputation: 471
If my understanding of loops is correct your transformation is completely valid, but this transformation seems to be a lot harder to read than the while loop. Just do the initialization before the while
loop and then increment at the end of the loop to get rid of the warning.
c = *s++;
while(c != '\0')
{
...
c = *s++;
}
Upvotes: 0
Reputation: 881243
The transformations are valid, yes, but they result in code that's harder to maintain, simply because there are two places you have to change the assignment.
I would be more inclined to figure out how to turn off that particular warning (even if it's localised with something like the gcc
#pragma warning
pragma) since it is, after all, perfectly valid C code, both syntactically and (in this case) semantically.
Upvotes: 4
Reputation: 16406
You haven't stated what your compiler is, but any compiler of quality allows such a warning to be turned off. But if you can't manage that:
for(;;)
{
c = *s++;
if (c == '\0') break;
...
}
is equivalent and is more general. Likewise:
for(;;)
{
i = getNext();
if (!i) break;
...
}
In many cases, better than the first one (but not equivalent) is:
for(;; s++)
{
c = *s;
if (c == '\0') break;
...
}
These are more verbose and ugly, but they are much better than your transformation that repeats the code, which is fragile and error-prone.
Upvotes: 0
Reputation: 476970
Personally, I'd write the first loop like this:
for (char c; (c = *s) != '\0'; ++s)
{
// ...
}
This makes it clear that the s
is the thing that's being incremented. You can also omit the != '\0'
, which is implicit.
I'd keep the second loop as a while
loop, or at least leave the assignment-inside-conditional. Maybe like this, to minimize scope pollution:
for (iterator i; i = getNext(); )
{
// ...
}
I personally find it quite acceptable to have part of the per-loop activity happening inside the conditional; that's natural for things like std::cin >> n
and std::getline(file, line)
, too.
Upvotes: 1