gpt4 book ai didi

c - 为什么我不能以这种方式复制终止空值?

转载 作者:太空宇宙 更新时间:2023-11-04 06:12:21 25 4
gpt4 key购买 nike

我想用下面的代码复制字符串,但它没有复制'\0'。

void copyString(char *to, char *from)
{
do{
*to++ = *from++;
}while(*from);
}
int main(void)
{
char to[50];
char from[] = "text2copy";
copyString(to, from);
printf("%s", to);
}

这是代码的输出:

text2copyÇ■   ║kvu¡lvu

每次我重新运行代码时,text2copy 之后的字符都会发生变化,所以 while(*from) 工作正常,但会复制一些随机的东西而不是 '\0'。

text2copyÖ■   ║kvu¡lvu
text2copy╨■   ║kvu¡lvu
text2copy╡■   ║kvu¡lvu
//etc

为什么会这样?

最佳答案

问题是您永远不会复制字符串末尾的 '\0' 字符。要了解为什么要考虑这一点:

传入的字符串是一个大小正好适合数据的常量字符串:

char from[] = "text2copy";

在内存中是这样的:

            ----+----+----+----+----+----+----+----+----+----+----+----   other memory |  t |  e |  x |  t |  2 |  c |  o |  p |  y | \0 | other memory            ----+----+----+----+----+----+----+----+----+----+----+----                   ^                 from

Now let's imagine that you have done the loop several times already and you are at the top of the loop and from is pointing to the 'y' character in text2copy:

            ----+----+----+----+----+----+----+----+----+----+----+----   other memory |  t |  e |  x |  t |  2 |  c |  o |  p |  y | \0 | other memory            ----+----+----+----+----+----+----+----+----+----+----+----                                                           ^                                                         from

The computer executes *to++ = *from++; which copies the 'y' character to to and then increments both to and from. Now the memory looks like this:

            ----+----+----+----+----+----+----+----+----+----+----+----   other memory |  t |  e |  x |  t |  2 |  c |  o |  p |  y | \0 | other memory            ----+----+----+----+----+----+----+----+----+----+----+----                                                                ^                                                              from

The computer executes } while(*from); and realizes that *from is false because it points to the '\0' character at the end of the string so the loop ends and the '\0' character is never copied.

Now you might think this would fix it:

void copyString(char *to, char *from)
{
do{
*to++ = *from++;
} while(*from);
*to = *from; // copy the \0 character
}

它确实复制了 '\0' 字符,但仍然存在问题。该代码甚至存在更根本的缺陷,因为正如@JonathanLeffler 在评论中所说,对于空字符串,您可以查看字符串末尾之后的内存内容,并且因为它没有分配给您访问它会导致未定义的行为:

            ----+----+----   other memory | \0 | other memory            ----+----+----                   ^                 from

The computer executes *to++ = *from++; which copies the '\0' character to to and then increments both to and from which makes from point to memory you don't own:

            ----+----+----   other memory | \0 | other memory            ----+----+----                        ^                      from

Now the computer executes }while(*from); and accesses memory that isn't yours. You can point from anywhere with no problem, but dereferencing from when it points to memory that isn't yours is undefined behaviour.

The example I made in the comments suggests saving the value copied into a temporary variable:

void copyString(char *to, char *from)
{
int test;
do{
test = (*to++ = *from++); // save the value copied
} while(test);
}

我建议采用这种特定方法的原因是要向您表明问题出在您正在测试的内容上,而不是事后测试循环条件。如果您保存复制的值然后稍后测试该保存的值,则该字符在测试之前被复制(因此\0 被复制)并且您不从递增的指针中读取(因此没有未定义的行为)

但@JonathanLeffler 在他的评论中的例子更短、更容易理解,也更地道。它在不声明命名临时变量的情况下做同样的事情:

void copyString(char *to, char *from)
{
while ((*to++ = *from++) != '\0')
;
}

代码首先复制字符,然后测试复制的值(因此 '\0' 将被复制)但是递增的指针永远不会取消引用(因此没有未定义的行为) .

关于c - 为什么我不能以这种方式复制终止空值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53734672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com