Search code examples
cstrncpy

Why can I subtract two pointers and use the result as a size?


In this code snippet, strncpy has the n value as a difference of two char pointers. How can two string pointers be subtracted? What is the value of n here?

The program does compile successfully but doesn't the size have to be an int value?

void replace(char *s1) { 
    char r[4][5] = { "get", "tell", "your", "house" };
    char rep[4][10] = { "see", "us", "tall", "kite" };
    char buff[500];
    int i;
    char *ch;

    for (i < 0; i < 4; i++) { 
        if ((ch = strstr(s1, r[i]))) {
            strncpy(buff, s1, ch - s1);
            buff[ch-s1] = 0; 
            sprintf(buff + (ch - s1), "%s%s", rep[i], ch + strlen(r[i])); 
            s1[0] = 0; 
            strcpy(s1, buff);

            return replace(s1);
        }
    }
}

Solution

  • If you have two pointers p and q that point into the same array, then p - q evaluates to the (signed) number of elements between p and q in the array. For example, consider this code:

    int array[137];
    int* p = &arr[10];
    int* q = &arr[5];
    
    ptrdiff_t diff = p - q;
    

    Here, p points to the tenth element of the array, q points to the fifth element of the array, so p - q would be five. (The special type ptrdiff_t is an integer type that’s big enough to hold the difference of any two pointers.)

    Another way to interpret this difference is to ask “what index does pointer p point to if we imagine the array starts where q is pointing?” In that case, the answer is five, since if we treat q as the base of the array, then p would be at index five. In your case, your pointer ch was set equal to the return value of strstr, so it points somewhere into the middle of s1. The expression ch - s1 then means “the position in the string where ch points.”

    Making an analogy to points in space: if you have two points p and q, you can think of p - q as a vector representing the direction you need to go to get from q to p. You can’t meaningfully add the points p and q to get p + q, though, just as you can’t add two pointers in C.