Подтвердить что ты не робот

Когда использовать strncpy или memmove?

(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);

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

4b9b3361

Ответ 1

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

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

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

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

Удачи!

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

От wikipedia:

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

Ответ 5

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

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

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

Ответ 6

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

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

Менее эффективен, но также работает, чтобы ограничить байты, записанные и нуль-завершающие строку:

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

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