1
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

输出是:

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

因此,我的问题是为什么

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

代替

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

作为'\0'空字符?

4

1 回答 1

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

这是错误的使用方式strncpy。您应该指定输出缓冲区的大小,而不是输入的大小。在这种情况下,输出缓冲区为 16 个字节,但您将 17 个字节复制到其中,这会导致未定义的行为。

请注意,即使您确实指定了输出缓冲区大小,strncpy如果字符串被截断,也不会写入空终止符,因此您需要自己添加它:

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

出于这个原因,有些人更喜欢使用其他功能。例如,您可以使用以下方法实现安全复制功能strncat

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

像这样使用:

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

另请注意,您实际上不会在预期的输出中看到空字符及其后面的内容。输出将仅在空终止符处停止,因为它指示字符串的结尾。

于 2013-11-11T20:08:02.893 回答