cpointerscharc-stringsindices

Can someone explain to me the performance difference of using pointers vs indices for accessing an array?


So I am learning C and to get practice I do some "LeetCode" challenges. For a palindrome checker I have tried two approaches, one using indices and one using pointers.

And as a follow up question:

enter image description here enter image description here

For reference here are the code blocks.

Pointers:

bool isPalindrome(char *s) {

    size_t length = strlen(s);
    char *left = s;
    char *right = s + length - 1;

    while (left < right) {
        
        while (left < right && !isalnum(*left))
            ++left;
        
        if (left == right)
            return true;

        while (right > left && !isalnum(*right))
            --right;

        if (right == left)
            return true;
        
        if (tolower(*left) != tolower(*right))
            return false;

        ++left;
        --right;
    }

    return true;
}

Indices:

bool isPalindrome(char *s) {

    size_t length = strlen(s);
    size_t left = 0;
    size_t right = length - 1;

    while (left < right) {
        
        while (left < right && !isalnum(s[left]))
            ++left;
        
        if (s[left] == '\0')
            return true;

        while (right > left && !isalnum(s[right]))
            --right;

        if (right == 0)
            return true;
        
        if (tolower(s[left]) != tolower(s[right]))
            return false;

        ++left;
        --right;
    }

    return true;
}

Solution

  • Where does the large performance difference come from?

    There are many potential reasons for a performance difference, but it would be helpful to understand how you compile the code, how you measure performance and with what input. Here are a few hints:

    What method is usually preferred and for what reasons?

    Both methods are equivalent if implemented properly, and compile to equivalent performance with modern compilers.

    Here are reasons to use pointers:

    Reasons to use index variables with type size_t:

    Before you focus on performance, focus on correctness!

    Here are modified versions:

    bool isPalindrome_idx(const char *s) {
        size_t len = strlen(s);
        if (len > 1) {
            size_t left = 0;
            size_t right = len - 1;
            while (left < right) {
                while (!isalnum((unsigned char)s[left])) {
                    if (++left >= right)
                        return true;
                }
                while (!isalnum((unsigned char)s[right])) {
                    if (left >= --right)
                        return true;
                }
                if (tolower((unsigned char)s[left]) != tolower((unsigned char)s[right])) {
                    return false;
                } else {
                    left++;
                    right--;
                }
            }
        }
        return true;
    }
    
    bool isPalindrome_ptr(const char *s) {
        size_t len = strlen(s);
        if (len > 1) {
            const char *left = s;
            const char *right = s + len - 1;
            while (left < right) {
                while (!isalnum((unsigned char)*left)) {
                    if (++left >= right)
                        return true;
                }
                while (!isalnum((unsigned char)*right)) {
                    if (left >= --right)
                        return true;
                }
                if (tolower((unsigned char)*left) != tolower((unsigned char)*right)) {
                    return false;
                } else {
                    left++;
                    right--;
                }
            }
        }
        return true;
    }