输出根据函数调用在程序中的位置而变化
Output changes depending on the position of the function call in the program
我目前正在学习 C。为了变得更好,我想做的一件事是模仿 header 中的 "strcat" 函数。为了制作更精确的副本,我将自己函数的输出与原始函数的输出进行了比较。它们使用相同但不同的 char 数组。但是,如果在原始函数之后调用,我自己的函数的输出会发生变化。这是两个代码变体:
在第一个中,原始的输出是 "1234567890123456",正如预期的那样,我自己的输出是 "123456789123456".经过几十次各种检查后,我发现:“0”字符一旦作为参数传递给函数,就会从 src[0] 中消失:
int main()
{
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Concatenate |%s| and |%s|\n", dest, src);
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
return 0;
}
但是,如果我像这样简单地重新定位函数的 printf:
int main()
{
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Concatenate |%s| and |%s|\n", dest, src);
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
return 0;
}
两个函数都将 return "1234567890123456" 作为输出。
问题是:这怎么可能?我很好奇,因为这些函数处理两组不同的数组,因此不应相互影响。出于某种原因,我的函数的行为取决于它在 int main().
的 body 中的调用时间。
请注意,我特意将 dest[] 数组设置为 10 个字符大,因为我想在意外情况下模仿原始 "strcat" 的行为出色地。尽管这可能是问题的核心,如果我更改它,代码在上述两种情况下都可以正常工作。正如我所说,我感兴趣的是问题的本质,而不是解决问题的方法。
我不确定我的函数的文本是否与此问题相关,但以防万一:
char *ft_strcat(char *dest, char *src)
{
int dest_end;
int src_count;
dest_end = 0;
src_count = 0;
while (dest[dest_end])
dest_end++;
while (src[src_count])
{
dest[dest_end] = src[src_count];
src_count++;
dest_end++;
}
dest[dest_end + 1] = '[=12=]';
return dest;
}
感谢您的任何回答。
这是由于内存重叠....
因为您要声明 dest1[10]
和 dest[10]
的大小
而不是像这样声明这两个具有更大长度的数组
char dest1[100];
char dest[100];
你的问题就迎刃而解了。
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
在这两种情况下,使用您自己的函数 ft_strcat(dest, src))
或 strcat()
,您调用 undefined behavior 因为目的地指向的 char
数组不可用保存初始化的字符串加上源指向的附加字符串。超出数组范围写入时,程序的行为未定义。
解决方案:
数组dest
和dest1
总共需要至少18
个元素,10
用于容纳"0123456789"
,7
对于终止空字符的附加 "0123456"
+ 1
元素 [=27=]
:
char dest[18] = "123456789";
char dest1[18] = "123456789";
char src[70] = "0123456";
char src1[70] = "0123456";
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
printf ("Normal people do: %s\n", strcat(dest1, src1));
旁注:
- 数组
scr1
是多余的,因为它只是用来提供追加的字符串,并且它的内容正好等于src
中的字符串。您也可以将 src
用于第二个附加过程:
printf ("Normal people do: %s\n", strcat(dest1, src));
src
和 src1
包含每个 70
元素,这是不必要的。他们都只需要有 8
个元素,而不是 70
:
src[8] = "0123456";
src1[8] = "0123456";
一个更方便的方法是省略元素的数量,让编译器自动检测所需的元素数量,这样也可以保证你在计数时不会忘记空字符:
src[] = "0123456";
src1[] = "0123456";
- 因为指针
src
及其指向的对象都不应在 ft_strcat()
内部进行修改,声明 src
为 char const * const src
。
dest
也可以设为 const
,但不要将其设为指向 const
字符的指针:char * const dest
.
关于指针 dest
.
,您还可以调整 ft_strcat()
的 return 类型
结果是:
char * const ft_strcat(char * const dest, char const * const src)
我目前正在学习 C。为了变得更好,我想做的一件事是模仿 header 中的 "strcat" 函数。为了制作更精确的副本,我将自己函数的输出与原始函数的输出进行了比较。它们使用相同但不同的 char 数组。但是,如果在原始函数之后调用,我自己的函数的输出会发生变化。这是两个代码变体:
在第一个中,原始的输出是 "1234567890123456",正如预期的那样,我自己的输出是 "123456789123456".经过几十次各种检查后,我发现:“0”字符一旦作为参数传递给函数,就会从 src[0] 中消失:
int main()
{
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Concatenate |%s| and |%s|\n", dest, src);
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
return 0;
}
但是,如果我像这样简单地重新定位函数的 printf:
int main()
{
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Concatenate |%s| and |%s|\n", dest, src);
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
return 0;
}
两个函数都将 return "1234567890123456" 作为输出。
问题是:这怎么可能?我很好奇,因为这些函数处理两组不同的数组,因此不应相互影响。出于某种原因,我的函数的行为取决于它在 int main().
的 body 中的调用时间。请注意,我特意将 dest[] 数组设置为 10 个字符大,因为我想在意外情况下模仿原始 "strcat" 的行为出色地。尽管这可能是问题的核心,如果我更改它,代码在上述两种情况下都可以正常工作。正如我所说,我感兴趣的是问题的本质,而不是解决问题的方法。
我不确定我的函数的文本是否与此问题相关,但以防万一:
char *ft_strcat(char *dest, char *src)
{
int dest_end;
int src_count;
dest_end = 0;
src_count = 0;
while (dest[dest_end])
dest_end++;
while (src[src_count])
{
dest[dest_end] = src[src_count];
src_count++;
dest_end++;
}
dest[dest_end + 1] = '[=12=]';
return dest;
}
感谢您的任何回答。
这是由于内存重叠....
因为您要声明 dest1[10]
和 dest[10]
的大小
而不是像这样声明这两个具有更大长度的数组
char dest1[100];
char dest[100];
你的问题就迎刃而解了。
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1));
在这两种情况下,使用您自己的函数 ft_strcat(dest, src))
或 strcat()
,您调用 undefined behavior 因为目的地指向的 char
数组不可用保存初始化的字符串加上源指向的附加字符串。超出数组范围写入时,程序的行为未定义。
解决方案:
数组dest
和dest1
总共需要至少18
个元素,10
用于容纳"0123456789"
,7
对于终止空字符的附加 "0123456"
+ 1
元素 [=27=]
:
char dest[18] = "123456789";
char dest1[18] = "123456789";
char src[70] = "0123456";
char src1[70] = "0123456";
printf ("Your filthy code: %s\n", ft_strcat(dest, src));
printf ("Normal people do: %s\n", strcat(dest1, src1));
旁注:
- 数组
scr1
是多余的,因为它只是用来提供追加的字符串,并且它的内容正好等于src
中的字符串。您也可以将src
用于第二个附加过程:
printf ("Normal people do: %s\n", strcat(dest1, src));
src
和src1
包含每个70
元素,这是不必要的。他们都只需要有8
个元素,而不是70
:
src[8] = "0123456";
src1[8] = "0123456";
一个更方便的方法是省略元素的数量,让编译器自动检测所需的元素数量,这样也可以保证你在计数时不会忘记空字符:
src[] = "0123456";
src1[] = "0123456";
- 因为指针
src
及其指向的对象都不应在ft_strcat()
内部进行修改,声明src
为char const * const src
。
dest
也可以设为 const
,但不要将其设为指向 const
字符的指针:char * const dest
.
关于指针 dest
.
ft_strcat()
的 return 类型
结果是:
char * const ft_strcat(char * const dest, char const * const src)