strncpy 产生奇怪的输出

strncpy making weird output

我正在尝试为 strncpy
制定算法 我在手册中阅读了它的工作原理并制定了我的算法
然后我做了一个测试,看看我的 ft_strncpy 和真正的 strncpy

有什么区别
#include <string.h>
#include <stdio.h>

char    *ft_strncpy(char *dest, char *src, unsigned int n)
{
    unsigned int    i;

    i = 0;
    while (i < n && src[i] != '[=10=]')
    {
        dest[i] = src[i];
        i++;
    }
    while (i < n)
    {
        dest[i] = '[=10=]';
        i++;
    }
    return (dest);
}

int main(void)
{
    char src1[] = "123456789q00000";
    char dest1[] = "zzz";
    printf("my output\n");
    printf("src1: %s\n", src1);
    ft_strncpy(dest1, src1, 8);
    printf("dest1: %s\n", dest1);

    printf("\nhow it should be\n");
    char src2[] = "123456789q00000";
    char dest2[] = "zzz";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 8);
    printf("dest2: %s\n", dest2);
}

how it should be 部分应该是真实 strncpy 的正确输出 但是我有奇怪的输出就像我提供的代码一样
我得到这个错误

*** buffer overflow detected ***: terminated
signal: aborted (core dumped)

我从手册中了解到的是
strncpyn 的第一个字符从 *src 复制到 *dest
所以像

这样的代码
    char src2[] = "123456789q00000";
    char dest2[] = "zzz";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 10);
    printf("dest2: %s\n", dest2);

应该输出:123456789q作为dest的值 我是不是漏了什么?

c 中的数组不是动态的,所以
我不能只用字符串初始化它然后尝试将其更改为更大的字符串
这将导致未定义的行为

此外还有一个 corner-case,它可能不会添加终止空字符,因此我将无法使用 printf 打印它,因为它不再是字符串,而是一个数组。

结论:修改字符串要谨慎
(在 @Someprogrammerdude and @n. 1.8e9-where's-my share m 的帮助下回答。)

strncpy(dest2, src2, 10); 有未定义的行为,因为它会修改以 dest2[0] 开头的 10 个字节,而 dest2 只有 4 个字节长。

出于同样的原因,您在 ft_strncpy(dest1, src1, 8); 中遇到了同样的问题。

使用具有未定义行为的代码进行的测试无法得出任何结论。必须先修正代码。

你为 ft_strncpy() 编写的代码似乎是正确的,除了长度参数的类型 unsigned int 应该是 size_t。使用 unsigned int 可能是您学校项目的一项要求,但值得商榷的是,除其他 counter-productive 要求外,例如禁止 for 循环和在 return 值周围强制使用括号。

这是修改后的版本:

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

char    *ft_strncpy(char *dest, char *src, unsigned int n)
{
    unsigned int    i;

    i = 0;
    while (i < n && src[i] != '[=10=]')
    {
        dest[i] = src[i];
        i++;
    }
    while (i < n)
    {
        dest[i] = '[=10=]';
        i++;
    }
    return (dest);
}

void dump(const char *prefix, const char *p, size_t size)
{
    size_t i;

    printf("%s: %s  [", prefix, p);
    i = 0;
    while (i < size) {
        printf(" %.2X", (unsigned char)p[i]);
        i++;
    }
    printf(" ]\n");
}
    
int main(void)
{
    char src1[] = "zzz";
    char dest1[] = "123456789q00000";

    printf("my output\n");
    printf("src1: %s\n", src1);
    ft_strncpy(dest1, src1, 8);
    dump("dest1: ", dest1, sizeof dest1);

    printf("\nhow it should be\n");
    char src2[] = "zzz";
    char dest2[] = "123456789q00000";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 8);
    dump("dest1: ", dest1, sizeof dest1);

    return 0;
}

输出:

my output
src1: zzz
dest1: : zzz  [ 7A 7A 7A 00 00 00 00 00 39 71 30 30 30 30 30 00 ]

how it should be
src2: zzz
dest1: : zzz  [ 7A 7A 7A 00 00 00 00 00 39 71 30 30 30 30 30 00 ]