基本的にstrlcpy
、1996 年に導入された を再発明しています。strlcpy と strlcat を参照してください。Todd C. Miller と Theo de Raadt による、一貫性のある安全な文字列のコピーと連結に関する論文です。glibc への追加が拒否されたため、聞いたことがないかもしれません。これは、glibc のメンテナーによって「恐ろしく非効率な BSD のがらくた」と呼ばれ、他のすべてのオペレーティング システムで採用されたときでさえ、今日まで戦っています。Damien Miller によるSecure Portabilityの論文を参照してください。 (パート 4: 適切な API の選択)。
Linux で strlcpy を使用するには、libbsdプロジェクト (Debian、Ubuntu、およびその他のディストリビューションにパッケージ化されています) を使用するか、Web で簡単に見つけられるソース コード (たとえば、この回答の 2 つのリンク) をコピーするだけです。
しかし、ここでソース文字列の長さを使用していない場合に最も効率的なものについての質問に戻ると、http://cvsweb.openbsd.org/cgi-binstrlcpy
のOpenBSD のソースに基づく私の考えです。 /cvsweb/src/lib/libc/string/strlcpy.c?rev=1.11ただし、元の文字列の長さをチェックしていないため、非常に長くなる可能性がありますが、適切な '\0' で終わる可能性があります。
char *d = str; // the destination in your example
const char *s = string; // the source in your example
size_t n = max; // the max length in your example
/* Copy as many bytes as will fit */
if (n != 0) {
while (--n != 0) {
if ((*d++ = *s++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL */
if (n == 0) {
if (max != 0)
*d = '\0'; /* NUL-terminate dst */
}
これは、 memcpy を使用するhttp://cantrip.org/strlcpy.cの strlcpy のバージョンです。
/*
* ANSI C version of strlcpy
* Based on the NetBSD strlcpy man page.
*
* Nathan Myers <ncm-nospam@cantrip.org>, 2003/06/03
* Placed in the public domain.
*/
#include <stdlib.h> /* for size_t */
size_t
strlcpy(char *dst, const char *src, size_t size)
{
const size_t len = strlen(src);
if (size != 0) {
memcpy(dst, src, (len > size - 1) ? size - 1 : len);
dst[size - 1] = 0;
}
return len;
}
どちらがより効率的かは、ソース文字列に依存すると思います。非常に長いソース文字列の場合、strlen に時間がかかる場合があり、元の長さを知る必要がない場合は、最初の例の方が速いかもしれません。
それはすべてデータに依存するため、実際のデータをプロファイリングすることが唯一の方法です。