Search code examples
cwhile-loopstrlenc89

Why does this function return the correct length of a string? (Incrementing a char pointer)


This is a function that counts the number of characters in a string:

int str_len(const char* s) {
    int i = 0;
    while(*(s++)) {
        i++;
    }
    return i;
}

Why does this return the correct length?

Let's say I call this function with a simple String "a". Then s is incremented in the while loop, therefore the value of s and i are both 0.


Solution

  • The value of s++ is the original value of s, before increment, the increment occurs at an unspecified time before the next sequence point.

    Hence *s++ and *(s++) are equivalent: they both dereference the original value of s. Another equivalent expression is *(0, s++) and, not for the faint of heart, such is this one: 0[s++]

    Note however that your function should use type size_t for i and its return type:

    size_t str_len(const char *s) {
        size_t i = 0;
        while (*s++) {
            i++;
        }
        /* s points after the null terminator */
        return i;
    }
    

    Here is a potentially more efficient version with a single increment per loop:

    size_t str_len(const char *s) {
        const char *s0 = s;
        while (*s++) {
            /* nothing */
        }
        return s - 1 - s0;
    }
    

    For those who wonder about the weird expressions in the second paragraph:

    • 0, s++ is an instance of the comma operator , that evaluates its left part, then its right part which constitutes its value. hence (0, s++) is equivalent to (s++).

    • 0[s++] is equivalent to (s++)[0] and *(0 + s++) or *(s++ + 0) which simplify as *(s++). Transposing the pointer and the index expressions in [] expressions is not very common nor particularly useful but conforms to the C standard.