Milos wrote:Dann Corbit wrote:No, actually, I am now convinced that the result is not unspecified. Even though the arguments can be evaluated in any order for any fragment between sequence points in the statement, in this case it does not matter.
After all, if it performs the first assignment before the second or the second before the first (for instance) the result is the same, since the assignments are identical.
You finally got it. The result of the original expression is in general case defined but unspecified. However, since all the elements are identical it is also specified. Since, compiler cannot distinguish a special case from a general one, it issues the warning.
The warning is syntactically correct but semantically wrong.
If the language guaranteed that scan could not point into the 4 bytes occupied by the pointer variable match, and vice versa, then the original expression would not be unspecified at all, because each subexpression of the form (*++p) has only one evaluation order, and each && is a sequence point. So the warning would be spurious in that case.
[Edit: between each sequence point, the two pointer increments have to occur before any reads that depend on the value of that pointer, so the result is unambigous even if there are multiple possible evaluation orders. Its possible the compiler does not track enough state or analyse that state in a nuanced enough way to detect this, though.]
However, if you allow the possibility of that bizarro aliasing, then the result of each comparison is now influenced by the order in which the increments and dereferences are evaluated. In which case the warning is legitimate, even though its about an aliasing situation which nobody would do deliberately.
Were scan and match declared as char* pointers? If thats the case, it might be forcing the compiler to assume that they could alias anything. Even if the compiler is able to prove in this particular case that the bizarro aliasing is impossible, its under no obligation to do that, and issuing the warning is a reasonable thing for it to do.
If they are char* pointers and that is the source of the problem, then it means two things:
(1) the compiler is probably generating stupid code for it also, and
(2) changing them to unsigned char*
might remove the bizarro potential aliasing, which would fix the warning and the bad codegen (but I'm not at all sure about this... try it and see.)
Edit: You could probably also replace it with this:
Code: Select all
do {
} while(
(++scan, ++match, *scan == *match) && (++scan, ++match, *scan == *match) &&
(++scan, ++match, *scan == *match) && (++scan, ++match, *scan == *match) &&
(++scan, ++match, *scan == *match) && (++scan, ++match, *scan == *match) &&
(++scan, ++match, *scan == *match) && (++scan, ++match, *scan == *match) &&
scan < strend);
But I think your version is clearer.