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)
我从手册中了解到的是
strncpy
将 n
的第一个字符从 *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 ]
我正在尝试为 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)
我从手册中了解到的是
strncpy
将 n
的第一个字符从 *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 ]