Note that the use of CMBC here was not thorough enough to spot that his reference implementation reads past the end of the string.
for (unsigned i=0; i<len; i++)
{
if (s[i]=='o' && s[i+1]=='k')
return i; // found
};
The last iteration of this loop, it accesses s[len-1] and s[len]. If the string is null terminated, that's OK. If it's really just a length qualified string, that's not OK.The later implementations treat len differently.
EDIT: It's worse than I said. The later version won't detect "ok" at the end of the string, because they are off by one in the OPPOSITE direction.
Note the second function is off by one in the opposite direction-- it doesn't find "ok" in "ok".
strncpy, despite what its name implies, does indeed not necessarily produce strings.
Regardless, a C string is defined to have a null terminator. All bets are off if you don't provide a string.
Even with a null terminator, there isn't a length that would work for both without overrunning the buffer.
printf("%d %d\n", search_ok_1("mok", 2), search_ok_2("mok", 2));
printf("%d %d\n", search_ok_1("mok", 3), search_ok_2("mok", 3)); /* Overruns without null term */
printf("%d %d\n", search_ok_1("mok", 4), search_ok_2("mok", 4)); /* Overruns even WITH null term */
Prints out: 1 2
1 3
1 1