Search code examples
cstringstrcpy

Why does strcpy omit the first character in source string when using destination string of size 1?


In C the strcpy function is used to copy a source into a destination string.

But when I use a destination char array of size 1 the strcpy correctly copies the source into the destination. But it also changes the source char array. I want to understand how this works in C.

I have done some research on how to correctly use strcpy in a program but all of them uses destination size more than 1. I did the program using destination size equal to 1. That's where the problem is.

char a[] = "String ABC";
char b[1];

strcpy(b, a);
int i;
// printf("%c\n", *(&(a[0])-1));

printf("%s\n",a);
printf("%s\n",b);

I expect the output to be

String ABC
String ABC

but the output I get is

tring ABC
String ABC

Solution

  • The problem is that you are copying to 1 byte string a longer string resulting in undefined behaviour.

    If you run this program:

    #include<stdio.h>
    #include<string.h>
    
    int main(int argc, char *argv[])
    {
        char a[] = "String ABC";
        char b[1];
        printf("%p\n", &a);
        printf("%p\n", &b);
    
        strcpy(b, a);
        int i;
        printf("%c\n", *(&(a[0])-1));
        printf("%c\n", a[0]);
        printf("%s\n",a);
        printf("%s\n",b);
        printf("%p\n", &a);
        printf("%p\n", &b);
    }
    

    you see b and a have contiguous addresses and b is stored in a memory address before a. Most likely strcpy copies the string to b but since b is not allocated to store such a long string, it overwrites the next contiguous memory cell which seems to be a.

    Let me indicate with || a memory cell storing a char. Suppose -b- is the cell storing one char long string. Before copy you have

    |-b-|---a memory allocation--|
    |-b-|S|t|r|i|n|g| |A|B|C|D|\n|
    

    Now a is copied into b: the second cell is the one of a which now contain t

      |--a memory allocation-|
    |S|t|r|i|n|g| |A|B|C|D|\n|
    

    This is what I suppose it is happening. But remember that copying a longer string into a shorter one will result in undefined behaviour.