What exactly does memcmp return?

1.7k Views Asked by At

I am trying to create my own memcmp file but whenever I compare it with original memcmp function the equal strings return zero but in case of unequal strings return values are different.

char *p = (char *)s1;
char *q = (char *)s2;
int charCompareStatus = 0;
if (s1 == s2) {
    return charCompareStatus;
}
while (n > 0) {
    if (*p != *q) {  
        charCompareStatus = (*p > *q) ? (*p - *q) : (*p - *q);
        break;
    }
    n--;
    p++;
    q++;
}
return charCompareStatus;

The output when compared to real memcmp function is

./a.out "ajinkya" "akinkya"

MEMCMP: -256

SST_MEMCMP: -1

4

There are 4 best solutions below

3
Aykhan Hagverdili On

The exact return values of strcmp and memcmp are not specified. They can return any negative value if the first argument is logographically less and any positive number if it's greater. So, a return value of -1, -10, -42 all mean the same thing.

3
chqrlie On

The exact value returned by memcmp() is not specified, only the sign matters and whether it is 0 or not.

Note however that your implementation is incorrect as the contents of memory are supposed to be compared as unsigned char values, not char values which may be negative.

Furthermore, the expression (*p > *q) ? (*p - *q) : (*p - *q) is redundant, you can just write *p - *q.

Here is a modified version:

int my_memcmp(const void *s1, const void *s2, size_t n) {
    unsigned char *p = s1;
    unsigned char *q = s2;

    if (s1 == s2) {  // optional.
        return 0;
    }
    while (n --> 0) {  // same as while (n-- > 0), iterating exactly n times
        if (*p != *q) {  
            return *p - *q;
        }
        p++;
        q++;
    }
    return 0;    
}
3
Luis Colorado On

Memcmp returns a positive number if first > second, negative for first < second, and 0 if both byte sequences are equal. This is done lexicographically, this is, the function decides at the first encountered difference.

The easiest way to compare both strings is:

int my_memcmp(
    const unsigned char *first,
    const unsigned char *second,
    size_t sz)
{
    while (sz--) {
        int cmp = *first++ - *second++;
        if (cmp == 0) continue;
        /* return the difference of the first 
         * pair that differs */
        return cmp;
    }
    return 0;
}

if you want to maintain the same prototype than the standard libray version, the you need to use void * pointers, and convert them internally to unsigned char *, as in:

int my_memcmp(
    const void *_first,
    const void *_second,
    size_t sz)
{
    const unsigned char 
        *first = _first,
        *second = _second;

    while (sz--) {
        int cmp = *first++ - *second++;
        if (cmp == 0) continue;
        return cmp;
    }
    return 0;
}

(you don't need to use const void *, as a void * is not dereferrable, and so, it is not modifiable)

Edit: the const modifiers added allow the calling routine to know that the target value cannot be modified by this routine, and this allows the compiler to optimize, based on that. (as the const void * can appear superfluous, because void type cannot be dereferenced, or accessed, if you convert a const void * to another kind of pointer, you'll get an error if you don't use a pointer to const also. This makes the const keyword recommendable even for void type.

0
Robert Zeff On

It appears to return the offset of the mismatch.