0

为什么这个 strncpy() 实现在第二次运行时崩溃,而第一次运行正常?

字符串

Copy characters from string 将n源的第一个字符复制到目标。如果在复制字符之前找到源 C 字符串的结尾(由空字符表示)n,则用零填充目标,直到总共n写入了字符。

如果源长度大于n(因此,在这种情况下,目标可能不是以空结尾的 C 字符串),则不会在目标末尾隐式附加空字符。

char *strncpy(char *src, char *destStr, int n)
{
    char *save = destStr; //backing up the pointer to the first destStr char
    char *strToCopy = src; //keeps [src] unmodified

    while (n > 0)
    {
        //if [n] > [strToCopy] length (reaches [strToCopy] end),
        //adds n null-teminations to [destStr]
        if (strToCopy = '\0') 
            for (; n > 0 ; ++destStr)
                *destStr = '\0';

        *destStr = *strToCopy;
        strToCopy++;
        destStr++;
        n--;

        //stops copying when reaches [dest] end (overflow protection)
        if (*destStr == '\0')
            n = 0; //exits loop
    }

    return save;
}

/////////////////////////////////////////////

int main()
{
    char st1[] = "ABC";
    char *st2;
    char *st3 = "ZZZZZ";
    st2 = (char *)malloc(5 * sizeof(char));


    printf("Should be: ZZZZZ\n");
    st3 = strncpy(st1, st3, 0);
    printf("%s\n", st3);

    printf("Should be: ABZZZZZ\n");
    st3 = strncpy(st1, st3, 2);
    printf("%s\n", st3);

    printf("Should be: ABCZZZZZ\n");
    st3 = strncpy(st1, st3, 3);
    printf("%s\n", st3);

    printf("Should be: ABC\n");
    st3 = strncpy(st1, st3, 4);
    printf("%s\n", st3);

    printf("Should be: AB\n");
    st2 = strncpy(st1, st2, 2);
    printf("%s\n", st2);

    printf("Should be: AB\n");
    st2 = strncpy(st1, st2, 4);
    printf("%s\n", st2);
}
4

3 回答 3

5

你得到一个分段错误,因为

char *st3 = "ZZZZZ";

目的地是一个字符串文字。不得修改字符串文字,并且它们通常存储在写保护的内存中。所以当你打电话

strncpy(st1, st3, n);

使用n > 0,您正在尝试修改字符串文字并导致崩溃(不一定,但通常)。

在复制循环中,您忘记取消引用strToCopy

if (strToCopy = '\0')

并写=而不是==,所以strToCopy设置为NULL,导致进一步取消引用 ofstrToCopy以调用未定义的行为。

于 2012-11-27T16:04:25.497 回答
2

我不认为你想要这个:

if (strToCopy = '\0') 

相反,您可能打算这样做:

if (*strToCopy == '\0') 

一般来说,使用yoda 条件可以让你从比较与赋值的混淆问题中解脱出来:

if ('\0' == *strToCopy)
于 2012-11-27T16:04:06.447 回答
0
while (n > 0)
    {
        //if [n] > [strToCopy] length (and reaches [strToCopy] end),
        //adds n null-teminations to [destStr]

        *destStr = *strToCopy;
        //stops copying when reaches [dest] end (overflow protection)
        if (*destStr == '\0')
            break; //exits loop
        strToCopy++;
        destStr++;
        n--;


    }
if (*destStr != '\0') *destStr = '\0';

主要是:

printf("Should be: ZZZZZ\n");
    st3 = strncpy(st1, st3, 0);
    printf("%s\n", st3);

这是错误的,因为您要复制的长度是0这样的,您将无法获得ZZZZZ

于 2012-11-27T16:09:07.647 回答