наилучшая практика - PullRequest
       32

наилучшая практика

1 голос
/ 28 июня 2019

У меня есть вопрос по поводу 3-го параметра памяти при работе со строкой.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 ]

4 голосов
/ 28 июня 2019

Поскольку вы начинаете с индекса 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) + 1 или strlen(...) + 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
2 голосов
/ 28 июня 2019

Ваша логика длины полностью отключена, и она работает только потому, что размер буфера слишком велик, а остаток в любом случае содержит нулевые байты. Вместо strlen(string1) против strlen(string1)+1, оно должно быть strlen(string1+6) против strlen(string1+6)+1. В этом случае вы обнаружите, что разница имеет значение, как вы ожидаете.

1 голос
/ 28 июня 2019

Определение строки включает в себя завершающий символ '\0'.

Не явно копировать этот завершающий символ, но обрабатывать результат как строку с нулевым символом в конце - неопределенное поведение.

Тамздесь нет «лучшей практики», кроме как не полагаться на неопределенное поведение.

0 голосов
/ 28 июня 2019

Вы перемещаете лишние байты.Длина правой части strlen(string1)-6.Когда вы перемещаете strlen(string1), вы перемещаете дополнительные 6 нулевых байтов после правой части строки, и они там, потому что с char string1[20]="Hello World"; неинициализированные байты инициализируются в \0.

...