重叠记忆最佳做法

时间:2019-06-28 17:28:10

标签: c memmove

我有一个关于在处理字符串时要记忆的第三个参数的问题。 strlen(string)strlen(string) + 1似乎产生相同的结果。我认为+1部分会 包含一个终止符\0,但似乎一切正常 都。这里有没有考虑的最佳实践?我已经看过这两个例子,但不确定该怎么做?

请考虑以下c程序:

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

int main()
{
   char string1[20]="Hello World";
   char string2[20]="Hello World";
   printf("\nstring1=\"%s\"\n",string1);

   memmove(string1,string1+6,strlen(string1) + 1);

   printf("\nstring1 after memmove \"%s\" using strlen(string1) + 1\n",string1);

   printf("\nstring2=\"%s\"\n",string2);

   memmove(string2,string2+6,strlen(string2));

   printf("\nstring2 after memmove \"%s\" using strlen(sting2)\n",string2);

   return 0;
}

输出:

string1="Hello World"

string1 after memmove "World" using strlen(string1) + 1

string2="Hello World"

string2 after memmove "World" using strlen(sting2)

4 个答案:

答案 0 :(得分:4)

由于您从索引6开始,strlen(...)strlen(...) + 1都过大了,并且正在复制字符串末尾的多余NUL字节。之所以起作用,是因为您制作了超大的char[20]数组,因此确实有额外的NUL。多余的数组插槽会用零填充,就像您写的一样:

char string1[20] = "Hello World\0\0\0\0\0\0\0\0\0";

您应该从两者中减去6。如果这样做,您会看到strlen(... + 6) + 1strlen(...) + 1 - 6是您想要的。从其中任何一个中删除+ 1,它不会复制NUL终止符,从而导致不同的结果:

string1 == "World\0World\0\0\0\0\0\0\0\0\0"  // with + 1, NUL copied
string2 == "World World\0\0\0\0\0\0\0\0\0"   // without + 1, NUL missing

答案 1 :(得分:2)

您的长度逻辑完全关闭,并且仅能工作,因为缓冲区过大,并且其余缓冲区总包含空字节。而不是strlen(string1) vs strlen(string1)+1,应该是strlen(string1+6) vs strlen(string1+6)+1。在这种情况下,您会发现差异确实很重要。

答案 2 :(得分:1)

字符串的定义包括结尾的'\0'字符。

未明确复制该终止字符,但仍将结果视为以null终止的字符串是未定义的行为。

除了不依赖未定义的行为,这里没有“最佳实践”。

答案 3 :(得分:0)

您正在移动多余的nul字节。的右侧长度为strlen(string1)-6。当您移动strlen(string1)时,您将在字符串的右侧再移动6个nul字节,它们在那里,因为使用char string1[20]="Hello World";,未初始化的字节被初始化为{{1} }。