2016-04-27 2 views
2

Я думал о создании альтернативы strncpy с завершением '\ 0' для моего собственного использования в файле заголовка, и мне интересно, какие из следующих подходов были бы лучше.strncpy() альтернатива - какие рекомендации для каждой версии?

int copystring(char *dest,char *source,int elements) 
{ 
    int run; 
    for(run=0;run<elements-1;run++)//last reserved for'\0' 
    { 
     dest[run]=source [run]; 
     if (dest[run]=='\0') 
     { 
      break; 
     } 

    } 
    dest[elements-1]='\0';//could make conditional but not neccesary. 
    return 0; 
} 

ИЛИ

int copystring(char *dest,char *source,int elements) 
{ 
     strncpy(dest,source,elements-1); 
     dest[elements-1]='\0'; 
     return 0; 
    } 

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

Как в стороне, почему strncpy() принимает size_t в качестве последнего аргумента? если это для передачи значений sizeof, которые будут полезны только в очень ограниченных обстоятельствах, не будет ли int int так же хорошо?

+1

Что это достижения, что 'strcopy' уже не предоставляют? Кроме того, почему вам нужно знать длину «char * source» с нулевым завершением, чтобы скопировать его? – CollinD

+0

У этого есть защита переполнения буфера для dest. i.e я буду использовать «элементы», чтобы передать максимальную длину адресата. – Orangesandlemons

+0

BTW: 'dest [run + 1] = '\ 0';' - >> 'dest [run] = '\ 0';' (запуск уже увеличивается после цикла) – wildplasser

ответ

2

Самый простой заменой strncpy() (если вы чувствуете, что вам нужен), вероятно, это:

dest[0] = '\0'; 
strncat(dest, source, size); 

strncat(), в отличие от strncpy(), гарантирует, что цель правильно завершающим нулем, а не копирует дополнительные null байты, когда цель больше, чем источник.

Но будьте уверены, что это поведение действительно то, что вы хотите. Если вы используете strcpy(), а целевой массив недостаточно велик, вы получите неопределенное поведение. С strncpy или strncat вы получите определенное поведение: значение тихо усечено. Если это то, что вы хотите, здорово - но это редко. Чаще всего усечение данных просто дает вам плохие данные, и вы должны обнаружить его и обрабатывать как ошибку, а не Procusteanly, отбрасывая все, что не подходит. (Imaging усечения "rm -rf $HOME/unimportant_directory""rm -rf $HOME" к перед передачей его system().)

Как и в сторону, почему strncpy() принять size_t как последний аргумент? если это для передачи sizeof значения, которые будут полезны только в очень ограниченных обстоятельствах, не было бы int так же хорошо?

size_t просто имеет смысл, поскольку это тип, используемый для представления размеров и длины. Использование int потребует определения (или оставления неопределенного) поведения для отрицательных аргументов и может ограничить размер строки, которую вы могли бы обрабатывать (если, например, int - 16 бит, а size_t - 32 бита). Вы всегда можете передать значение int, и оно будет неявно преобразовано в size_t.

Другой вариант - это нестандартная функция strlcpy(). Он не доступен для всех систем, но вы должны его установить (например, используя пакет libbsd-dev для систем Debian/Ubuntu/...) или создать его из источника.

Кстати, вот моя тирада на тему strncpy():
http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html

+0

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

+1

. Примечание: важно, чтобы 'размер' не превышал размер пространства, на который указывает' dest'. 2) BTW: хороший выбор между опциями OP 2: ни – chux

+0

Одним из недостатков этого является то, что для инициализации dest [0] с '\ 0' потребуется инициализировать dest [0], в то время как в идеале у меня будет как можно меньше кода. Я все еще пытаюсь разработать способ освобождения от необходимости указывать моей функции размер целевого массива в случаях, когда массив распался на указатель и т. Д. – Orangesandlemons

Смежные вопросы