Search code examples
cmemcpy

memcpy prepending instead mem write?


char str[50];
char strToCopy[16];
int numberOfBytesToFill = 7; // fills 1st n bytes of the memory area pointed to
char charToFillInAs = '*'; //48: ascii for '0' // '$';
void* targetStartAddress = str;
strncpy(strToCopy, "tO sEe The wOrLd", strlen("tO sEe The wOrLd")+1);
puts(strToCopy); // print

strcpy(str, "Test statement !@#$%^&*()=+_~```::||{}[]");
puts(str); // print

memset(targetStartAddress, charToFillInAs, numberOfBytesToFill); // fill memory with a constant byte (ie. charToFillInAs)
puts(str); // print

memcpy(targetStartAddress, strToCopy, strlen(strToCopy)+1); // +1 for null char   
puts(str); // print

The output is:

tO sEe The wOrLd
Test statement !@#$%^&*()=+_~```::||{}[]
*******atement !@#$%^&*()=+_~```::||{}[]
tO sEe The wOrLd*******atement !@#$%^&*()=+_~```::||{}[]       

Hence, my question is why

tO sEe The wOrLd*******atement !@#$%^&*()=+_~```::||{}[]       

instead of

tO sEe The wOrLd\0#$%^&*()=+_~```::||{}[]

with '\0' as the null char?


Solution

  • strncpy(strToCopy, "tO sEe The wOrLd", strlen("tO sEe The wOrLd")+1);
    

    This is the wrong way to use strncpy. You should specify the size of the output buffer, not the size of the input. In this case the output buffer is 16 bytes, but you are copying 17 bytes into it, which results in undefined behavior.

    Note that even if you do specify the output buffer size, strncpy won't write the null terminator if the string is truncated so you'd need to add it yourself:

    strncpy(strToCopy, "tO sEe The wOrLd", sizeof(strToCopy));
    strToCopy[sizeof(strToCopy)-1] = '\0';  //null terminate in case of truncation.
    

    For this reason, some people prefer to use another function. For example, you can implement a safe copy function by using strncat:

    void safeCopy(char *dest, const char *src, size_t destSize) {
        if (destSize > 0) {
            dest[0] = '\0';
            strncat(dest, src, destSize-1);
        }
    }
    

    To be used like:

    safeCopy(strToCopy, "tO sEe The wOrLd", sizeof(strToCopy));
    

    Note also that you won't actually see the null character and what comes after it as in your expected output. The output will simply stop at the null terminator because it indicates the end of the string.