Search code examples
cpointerssegmentation-faultnull-character

How does the function Strrchr finds the last c if c == '\0'?


Given for example a char *p that points to the first character in "there is so \0ma\0ny \0 \\0 in t\0his stri\0ng !\0\0\0\0", how would Strrchr() find the last occurrence of null-character?

the following questions arises:
=>What conditions would it depend on to stop the loop!
=>I think in all cases it'll try to access the next memory area to check for its condition?at some point bypassing the string boundaries, UB! so is it safe !

please if i'am wrong feel free to correct me!


Solution

  • It's very simple, as explained in the comments. The first \0 is the last and the only one in a C string.

    So if you write

    char *str = "there is so \0ma\0ny \0 \\0 in t\0his stri\0ng !\0\0\0\0";
    char *p = strrchr(str, 's');
    printf("%s\n", p);
    

    it will print

    so 
    

    because strchr will find the 's' in "so", which is the last 's' in the string you gave it. And (to answer your specific question) if you write

    p = strrchr(str, '\0');
    printf("%d %s\n", (int)(p - str), p+1);
    

    it will print

    12 ma
    

    proving that strchr found the first \0.

    It's obvious to you that str is a long string with some embedded \0's in it. But, in C, there is no such thing as a "string with embedded \0's in it". It is impossible, by definition, for a C string to contain an embedded \0. The first \0, by definition, ends the string.


    One more point. You had mentioned that if you were to "access the next memory area", that you would "at some point bypassing the string boundaries, UB!" And you're right. In my answer, I skirted with danger when I said

    p = strrchr(str, '\0');
    printf("%d %s\n", (int)(p - str), p+1);
    

    Here, p points to what strrchr thinks is the end of the string, so when I compute p+1 and try to print it using %s, if we don't know better it looks like I've indeed strayed into Undefined Behavior. In this case it's safe, of course, because we know exactly what's beyond the first \0. But if I were to write

    char *str2 = "hello";
    p = strrchr(str2, '\0');
    printf("%s\n", p+1);         /* WRONG */
    

    then I'd definitely be well over the edge.