Когда использовать strncpy или memmove? - PullRequest
17 голосов
/ 21 мая 2010

(gcc 4.4.4 c89)

Я всегда использовал strncpy для копирования строк. Я никогда особо не использовал memmove или memcpy. Однако мне просто интересно, когда вы решите, использовать ли strncpy, memmove или memcpy?

Код, который я пишу, предназначен для клиент-серверного приложения. В документации они используют bcopy. Однако могу ли я сделать то же самое с остальными?

bcopy((char*)server->h_addr,
      (char*)&serv_addr.sin_addr.s_addr,
      server->h_length);

Большое спасибо,

Ответы [ 6 ]

22 голосов
/ 22 мая 2010

strncpy() используется для копирования данных из источника в каталог заданного размера, копирование (заполнение) 0x00 с, если в исходном массиве (строке) до конца буфер. В отличие от strcpy, который будет блаженно копироваться до тех пор, пока не будет найден 0 байт - даже если указанный байт находится далеко за пределами вашего буфера.

memcpy() используется для копирования из источника в каталог независимо от того, что содержат исходные данные. Он также имеет тенденцию быть очень аппаратно оптимизированным и часто будет читать системные слова (int с / long с) за раз, чтобы ускорить копирование, когда выравнивание позволяет.

memmove() используется для копирования из перекрывающейся области источника и места назначения (скажем, перемещение содержимого массива вокруг себя или чего-то подобного - отсюда и мнемоника перемещения). Он использует стратегии (например, возможно копирование данных, начиная сзади, а не спереди), чтобы защитить от проблем, вызванных перекрывающимися регионами. Это также может быть немного менее эффективно, поскольку обычно аппаратная помощь не позволяет копировать данные задом наперед.

bcopy() и его родственники (bzero, и несколько других) - это функция копирования байтов, которую я видел время от времени во встроенной земле. Обычно он копирует данные по одному байту за раз из источника в место назначения, чтобы предотвратить проблемы с неправильной адресацией памяти, хотя любой хороший memcpy справится с этим, поэтому его использование довольно часто подозрительно.

Удачи!

12 голосов
/ 21 мая 2010

Вы никогда не должны использовать strncpy (если вы не имеете дело с той редкой специфической ситуацией, для которой он был представлен).Функция не предназначена для использования с C-строками с нулевым символом в конце.Название, данное этой функции, является просто исторической ошибкой и является основным источником путаницы для людей, которые пытаются ее использовать.strncpy - это функция, представленная для поддержки так называемых строк «фиксированной ширины», а не строк с нулевым символом в конце.Использование strncpy со строками с нулевым символом в конце является плохой практикой программирования, даже если вы можете использовать это для некоторого сходства с «работой» для этой цели.

Функция для «безопасного» копирования строк ограниченной длины не существуетоднако в библиотеке C некоторые реализации предоставляют его под именем strlcpy, которое уже стало де-факто стандартным именем для этой функции.Если ваша реализация не обеспечивает strlcpy, реализуйте ее самостоятельно.

Также верно, что во многих случаях вы можете заменить функцию str... функциями mem..., т.е. когда вы знаете точное числосимволы для копирования.

6 голосов
/ 21 мая 2010

strcpy (и другие методы str *) останавливаются при обнаружении байта NULL (0). memcpy и связанные с ними функции НЕ останавливаются при обнаружении байта NULL.

Если у вас есть двоичные данные, вы должны использовать memcpy. В вашем примере вы копируете двоичные данные, а не строковые данные.

strncpy является особым случаем, когда он прекращает копирование с байтом NULL, но продолжает заполнять вывод значениями NULL до указанной длины.

5 голосов
/ 21 мая 2010

Если вам не нужно поведение заполнения буфера strncpy, но вы хотите, чтобы безопасность не переполняла буфер, рассмотрите strlcpy

Из Википедия :

strlcpy предлагает две функции, разработанные, чтобы помочь разработчикам программного обеспечения избежать проблем. Функция принимает размер места назначения в качестве параметра, избегая переполнения буфера, если параметр размера является правильным. Если этот размер больше нуля, нулевой байт всегда записывается в место назначения, поэтому результирующая строка всегда заканчивается нулем (даже если исходная строка была усечена до соответствия).

4 голосов
/ 21 мая 2010

Используйте strncpy(), только если вы знаете, что для строки достаточно места - потому что это не гарантирует нулевое завершение, и чрезмерно восторженно, если место назначения намного короче исходной строки (потому что это пустое заполнение строки до полного длина). И если вы знаете длину, вы можете использовать memmove() ...

Если вы знаете длину строк, memmove() - разумный выбор - и номинально быстрее, чем strncpy(), потому что он не должен проверять наличие нулей в процессе работы; он просто копирует соответствующее количество байтов. (Я притворяюсь, что memcpy() не существует, так как он может потерпеть неудачу, если области памяти источника и назначения перекрываются, тогда как memmove() сделает это правильно независимо.)

Думайте о bcopy() как об архаичном варианте функций mem*().

2 голосов
/ 22 мая 2010

Если вы ищете безопасный / быстрый способ копирования, я доволен следующей техникой:

memcpy( dest, src, sizeof (dest));
dest[sizeof(dest) - 1] = '\0';       // ensure null termination

Менее эффективно, но также работает для ограничения записанных байтов и завершения строки нулем:

sprintf( dest, sizeof (dest), "%s", src);

Также возвращает количество байтов, которое он записал, чтобы вы могли определить, произошло ли усечение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...