Search code examples
arrayscstringstrcat

Pointer arithmetic in C when used as a target array for strcat()


When studying string manipulation in C, I've come across an effect that's not quite what I would have expected with strcat(). Take the following little program:

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

int main()
{
    char string[20] = "abcde";
    strcat(string + 1, "fghij");
    printf("%s", string);

    return 0;
}

I would expect this program to print out bcdefghij. My thinking was that in C, strings are arrays of characters, and the name of an array is a pointer to its first element, i.e., the element with index zero. So the variable string is a pointer to a. But if I calculate string + 1 and use that as the destination array for concatenation with strcat(), I get a pointer to a memory address that's one array element (1 * sizeof(char), in this case) away, and hence a pointer to the b. So my thinking was that the target destination is the array starting with b (and ending with the invisible null character), and to that the fghij is concatenated, giving me bcdefghij.

But that's not what I get - the output of the program is abcdefghij. It's the exact same output as I would get with strcat(string, "fghij"); - the addition of the 1 to string is ignored. I also get the same output with an addition of another number, e.g. strcat(string + 4, "fghij");, for that matter.

Can somebody explain to me why this is the case? My best guess is that it has to do with the binding precedence of the + operator, but I'm not sure about this.

Edit: I increased the size of the original array with char string[20] so that it will, in any case, be big enough to hold the concatenated string. Output is still the same, which I think means the array overflow is not key to my question.


Solution

  • You will get an output of abcdefghij, because your call to strcat hasn't changed the address of string (and nor can you change that – it's fixed for the duration of the block in which it is declared, just like the address of any other variable). What you are passing to strcat is the address of the second element of the string array: but that is still interpreted as the address of a nul-terminated string, to which the call appends the second (source) argument. Appending that second argument's content to string, string + 1 or string + n will produce the same result in the string array, so long as there is a nul-terminator at or after the n index.

    To print the value of the string that you actually pass to the strcat call (i.e., starting from the 'b' character), you can save the return value of the call and print that:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char string[20] = "abcde";
        char* result = strcat(string + 1, "fghij"); // strcat will return the "string + 1" pointer
        printf("%s", result); // bcdefghij
    
        return 0;
    }