Я следую правилам здесь . Позвольте мне процитировать его
strncpy
изначально был введен в библиотеку C для работы с полями имен фиксированной длины в таких структурах, как записи каталога. Такие поля не используются так же, как строки: завершающий нуль не нужен для поля максимальной длины, а задание байтов для более коротких имен равным нулю обеспечивает эффективное сравнение по полю. strncpy по происхождению не является «ограниченным strcpy», и Комитет предпочел признать существующую практику, а не изменять функцию, чтобы лучше подходить ей для такого использования.
По этой причине вы не получите завершающий '\0'
в строке, если вы нажмете n
, не найдя '\0'
из исходной строки до сих пор. Его легко использовать неправильно (конечно, если вы знаете об этой ловушке, вы можете избежать ее). Как говорится в цитате, он не был задуман как ограниченный strcpy. И я бы предпочел не использовать его, если не нужно. В вашем случае явно его использование не является необходимым, и вы это доказали. Зачем тогда это использовать?
И, вообще говоря, программный код также направлен на уменьшение избыточности. Если вы знаете, что у вас есть строка, содержащая «n» символов, зачем указывать функции копирования копировать максимальные n
символов? Вы делаете избыточную проверку. Дело не столько в производительности, сколько в согласованности кода. Читатели спросят себя, что может strcpy
сделать, чтобы они могли пересекать символы n
и что необходимо ограничить копирование, просто прочитав в руководствах, что этого не может произойти в этом случае. И тут начинаются путаницы среди читателей кода.
Для рационального использования mem-
, str-
или strn-
я выбрал среди них, как в приведенном выше связанном документе:
mem-
когда я хочу скопировать необработанные байты, например, байты структуры.
str-
при копировании строки с нулевым символом в конце - только при 100% переполнения не может быть.
strn-
при копировании строки с нулевым символом в конце до некоторой длины, заполняя оставшиеся байты нулем. Вероятно, не то, что я хочу в большинстве случаев. Легко забыть этот факт с помощью завершающего нулевого заполнения, но это так, как объясняет приведенная выше цитата. Итак, я бы просто написал свой собственный маленький цикл, который копирует символы, добавив завершающий '\0'
:
char * sstrcpy(char *dst, char const *src, size_t n) {
char *ret = dst;
while(n-- > 0) {
if((*dst++ = *src++) == '\0')
return ret;
}
*dst++ = '\0';
return ret;
}
Всего несколько строк, которые делают именно то, что я хочу. Если бы я хотел "сырую скорость", я все еще мог бы искать портативную и оптимизированную реализацию, которая делает именно эту работу bounded strcpy . Как всегда, сначала профиль, а затем возиться с ним.
Позже C получил функции для работы с широкими символами, названные wcs-
и wcsn-
(для C99
). Я бы использовал их также.