As it's written now, this code will only test the first byte of the inputs. The else return 0 needs to be moved out of the loop, leaving return 0 at the end:
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
}
return 0;
}
I guess since char signedness is implementation defined, you could make your comparison unsigned:
int memcmp_test(const char *cs_in, const char *ct_in, size_t n)
{
size_t i;
const unsigned char * cs = (const unsigned char*) cs_in;
const unsigned char * ct = (const unsigned char*) ct_in;
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
}
return 0;
}
From the C Standard (7.24.4.1 The memcmp function)
Returns
3 The memcmp function returns an integer greater than, equal to, or less than zero, accordingly as the object pointed to by s1 is greater than, equal to, or less than the object pointed to by s2.
The C Standard (C2x) specifies this:
7.26.4 Comparison functions
The sign of a nonzero value returned by the comparison functions
memcmp,strcmp, andstrncmpis determined by the sign of the difference between the values of the first pair of characters (both interpreted asunsigned char) that differ in the objects being compared.[...]
The
memcmpfunction returns an integer greater than, equal to, or less than zero, accordingly as the object pointed to bys1is greater than, equal to, or less than the object pointed to bys2.
The posted code for memcmp is just a possible implementation. The C Standard does not specify the exact return value for blocks with different contents, just the sign of the return value. Hence returning s1[-1] - s2[-1] is just as compliant as returning s1[-1] < s2[-1] ? -1 : 1 or 1 - 2 * (s1[-1] < s2[-1])
Note also that your implementation has problems:
- it makes no sense to test
((char *)s1)[i] == '\0')asmemcmpdoes not stop on any null terminator. - comparing the byte values as
charvalues is incorrect: the C Standard specifies that the comparison must be performed using theunsigned charvalues.
Here is a modified version:
#include <stddef.h>
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
size_t i;
i = 0;
if (n == 0)
return (0);
while (((unsigned char *)s1)[i] == ((unsigned char *)s2)[i])
{
i++;
if (i == n)
{
return (0);
}
}
if (((unsigned char *)s1)[i] < ((unsigned char *)s2)[i])
return (-1);
else
return (1);
}
The main function is incorrect:
- it must only check for zero values and that the signs of
ftandlibmatch if both are non zero. - the
countpassed to both functions should not exceed the size of the objects. This explains why you get inconsistent results whencountis greater than7for the identical strings: the contents of memory beyond the first 8 or so bytes or the identical strings differ. Reading the bytes beyond the end of the strings (ie: after the null terminator) has undefined behavior anyway.
Here is a modified version:
int main(void) {
const char *test_strings1[] = {
"fdjkDKDJFLDkjdfkjdf", "-456", "ALO marciano!!!", "xc42:",
" 7894545989828547", " +99", "abc123", "12abc", ""
};
const char *test_strings2[] = {
"fdjkDKDJFLDSkjdfkjdf", "-456", "ALO_ALO marciano!!!", "xc42",
" 789454598982854752", " +99", "abc123", "12abc", ""
};
int test_count = sizeof(test_strings1) / sizeof(*test_strings1);
for (int i = 0; i < test_count; i++) {
size_t size1 = strlen(test_strings1[i]) + 1;
size_t size2 = strlen(test_strings2[i]) + 1;
for (size_t count = 0; count <= size1 && count <= size2; count++) {
int ft = ft_memcmp(test_strings1[i], test_strings2[i], count);
int lib = memcmp(test_strings1[i], test_strings2[i], count);
if ((ft < 0 && lib >= 0)
|| (ft == 0 && lib != 0)
|| (ft > 0 && lib <= 0)) {
printf("*** Wrong!!! lib %i ft %i count = %zu string = %i ***\n",
lib, ft, count, i);
}
}
}
return 0;
}