mengxinayan
mengxinayan

Reputation: 11

Why `strncmp()` return a fault value in a special case?

I wrote a small code piece of code in C to test strncmp(), memcmp() functions. Here is the code.

#include <stdio.h>
#include <string.h>

int main()
{
    const char s1[] = "abcd\0\0\0\0";
    const char s2[] = "abcd\0abc";
    
    printf("strncmp(s1, s2, 4) = %d\n", strncmp(s1, s2, 5)); //0
    printf("strncmp(s1, s2, 8) = %d\n", strncmp(s1, s2, 8)); // why returns 0? Thx
    printf("memcmp(s1, s2, 4) = %d\n", memcmp(s1, s2, 5)); // 0
    printf("memcmp(s1, s2, 8) = %d\n", memcmp(s1, s2, 8)); // -120

    return 0;
}

I found strncmp(s1, s2, 8) = 0 while memcmp(s1, s2, 8) = -97. Because \0 is not equal to a, I think strncmp(s1, s2, 8) should return a non-zero value.

Then I tried to print s1 and s2 lengths, both of them are 9. And I tried to test more cases, strncmp() works as expected.

Finally, I tried a similar case as s1 and s2, strncmp returns a fault value. The following is my code:

#include <stdio.h>
#include <string.h>

int main()
{
    const char s1[] = "abcd\0\0\0\0";
    const char s2[] = "abcd\0xyz";
    
    printf("strncmp(s1, s2, 4) = %d\n", strncmp(s1, s2, 5)); //0
    printf("strncmp(s1, s2, 8) = %d\n", strncmp(s1, s2, 8)); // why returns 0? Thx
    printf("memcmp(s1, s2, 4) = %d\n", memcmp(s1, s2, 5)); // 0
    printf("memcmp(s1, s2, 8) = %d\n", memcmp(s1, s2, 8)); // -120

    printf("sizeof(s1) = %lu\n", sizeof(s1)); // 9
    printf("sizeof(s2) = %lu\n", sizeof(s2)); // 9

    printf("%d\n", strncmp("\0", "a", 1)); // -1
    printf("%d\n", strncmp("\0\0", "ab", 2)); // -1
    printf("%d\n", strncmp("a\0", "ab", 2)); // -1

    printf("%d\n", strncmp("a\0\0", "a\0b", 3)); // 0, why?

    return 0;
}

I guess maybe strncmp() will not compare characters after it meets \0? Isn't that how strcmp works. I'm not sure that strncmp() works like strcmp().

Upvotes: 1

Views: 200

Answers (2)

H.S.
H.S.

Reputation: 12679

I guess maybe strncmp() will not compare characters after it meets \0?

Yes, this is correct.

Isn't that how strcmp works. I'm not sure that strncmp() works like strcmp().

strcmp() compares two null-terminated byte string.

strncmp() compares not more than count characters (characters that follow a null character are not compared) [where count is the third argument passed to strncmp()].

For e.g.:

    const char s1[] = "abcd\0\0\0\0";
    const char s2[] = "abcd\0xyz";

The following statements will do exactly same comparison i.e. both will compare first 5 characters and return the result 0 (contents of both the strings are same) because the first 5 characters in both the string is same and 5th character is null character (\0):

    strncmp (s1, s2, 8);
    strcmp (s1, s2);

strncmp() will produce same result for the third argument value 7, 6 and 5 passed to it.

But consider following case:

    strncmp (s1, s2, 4); 
    strcmp (s1, s2);

In this case, though, both will return 0 (same strings) but the comparison performed by strncmp() and strcmp() is different. strncmp() will compare only first 4 characters, whereas, strcmp() will compare till it finds null character. Same for third argument value 3, 2, 1 and 0 passed to strncmp().

Take another example:

    const char s1[] = "abcdef";
    const char s2[] = "abcde";

strcmp (s1, s2) will never return equal for these strings, but
strncmp (s1, s2, 5 /*or 4/3/2/1/0 */) will compare them equal.

Another point,

Then I tried to print s1 and s2 lengths, both of them are 9.

Note that, sizeof does not give length but it gives the size of the object (or type) in bytes. If you want to calculate the length of a string, use strlen().


Couple of points to remember:

1). strncmp() does not compare characters following the null character.

2). One of the main difference between memcmp() and strncmp() is that strncmp() honour1) the null character while doing comparison but memcmp() doesn't.

Upvotes: 1

gagan
gagan

Reputation: 133

Per the man pages, your suspicion is correct:

Because strncmp() is designed for comparing strings rather than binary data, characters that appear after a `\0' character are not compared.

Concatenating two null-terminated strings as a single string with two null characters will only result in the first portion being displayed.

Upvotes: 4

Related Questions