I would like to compare a nul-terminated string against a string literal. I hope to use std::equal
and am curious if this code is well-defined according to the C standard:
#include <algorithm>
bool is_foo(const char *str) {
const char *lit = "foo";
return std::equal(lit, lit 4, str);
}
If std::equal
is guaranteed to stop at the first mismatch, then this code seems defined to me even if str
has length < 3. If there is no such guarantee then I think this may dereference past the end of str
resulting in UB.
What if anything does the C spec say about this? Thanks for any help!
CodePudding user response:
My reading of the C standard indicates that this is pedantically undefined behavior based on the following remark:
Remarks: If last2 was not given in the argument list, it denotes first2 (last1 - first1) below.
This is referring to overloads of std::equal
that do not supply the second sequence's ending iterator. In this case this would not be a valid pointer, hence this is pedantically undefined behavior, given the following part of the specification:
E be: pred(*i, *(first2 (i - first1))) for the overloads with no parameter proj1;
...
Returns: If last1 - first1 != last2 - first2, return false. Otherwise return true if E holds for every iterator i in the range [first1, last1) Otherwise, returns false.
I see nothing here that guarantees short circuit evaluation. The complexity does not seem to imply guaranteed short-circuit evaluation, either:
Complexity:
[ ... ]
... at most min(last1 - first1, last2 - first2) applications of ...
The "at most" part is not qualified in any way. Strictly interpreted this allows, but not requires, short-circuit evaluation.