【C言語】strcpyとstrncpyとstrlcpy

対象 strcpyとstrncpyとstrlcpyの3つの違いがわかりにくい人。

書いている人 プログラミング歴3年くらい

前提 C言語ざっくりわかる

環境 M1 mac

とある課題でstrlcpyの再現を行うことになり、cpy系のそれぞれの違いが頭に入りづらかったのでまとめておく。
なお挙動については保証しません。

まずは、とりあえずマニュアルを見よう。

ターミナルを開いて、manコマンドでstrcpyとすると、strcpyとstrncpyそれぞれの概要や定義が表示されるはずだ。

strcpyとstrncpyについては出てくる。

strlcpyに関しては、ここには表示されないので、man strlcpyとしてあげよう。

strlcpyのマニュアルが表示された。

では、それぞれ実装していく。

目次

strcpyの再現

strcpyは、二つの文字列を受け取って、それをもう片方にコピーする関数だ。

dstはdestination(目的地)の略、srcはsorce(コピー元)の意味で、srcからdstに文字をコピーしていく。英単語を覚えるとわかりやすい。コードの実装例は以下で、srcがnull文字になるまで、dstにコピーしていくだけだ。

char *my_strcpy(char * dst, const char * src)
{
	int	i;

	i = 0;
	while (src[i] != '\0')
	{
		dst[i] = src[i];
		i++;
	}
	return (dst);
}

strncpyの再現

strncpyの再現は以下の通り。strncpyはstrcpyに引数が1つ追加される。size_t lenの部分だ。len回文、srcからdstに文字をコピーしていく。

char *my_strncpy(char * dst, const char * src, size_t len)
{
	size_t i;

	i = 0;
	while (i < len && src[i])
	{
		dst[i] = src[i];
		i++;
	}
	while (i < len)
		dst[i++] = '\0';
	return (dst);
}

この関数の注意点は、lenの長さがsrcの長さより短い場合、dstがnull止めされないので、最終的にnull止めされてない文字列になってしまうことがある。

manに上の注意点が書いてある。

strlcpyの再現

strlcpyは必ずnull止めを保証してくれる関数。ただし、帰り値はunsigned intなので注意。実装コードは以下。

srcからdstにdstsize-1文コピーしてくれる。マイナス1する理由は最後にnull文字を入れる為。

関数のプロトタイプは以下。(restrictはよくわかりません。)

manコマンドで確認。
//作成しようとされる文字列の長さを返す。つまり、dstからsrcにコピーされるので期待されるのはsrcの長さ。
//だから返されるのはsrcの長さ
 size_t my_strlcpy(char *  dst, const char *  src, size_t dstsize)
 {
	size_t	i = 0;
	while (src[i])
		i++;
  if (dstsize == 0)
		return (i);
	size_t j = 0;
	while (j < (dstsize - 1) && src[j] != '\0')
	{
		dst[j] = src[j++];
	}
	dst[j] = '\0';
	return (i);
 }

dstsizeにはnullを入れる為の余裕をとっておく必要がある。

返す値はsrcの長さ。

srcからdstにうまくコピーされたら、srcの文字数分はいる。しかもヌル止めが保証されたままだ。

strlcpy(dst, array, sizeof(dst))が一番使い勝手良さそう。

dstsizeが0だった時もsrcの長さ返すっぽい。

まとめ

strlcpyなら必ずnull止めしてくれるみたいなので、安心。dstsizeが0だった場合もsrcの長さ返してくれる。そこは注意して使う必要があるみたい。

結局manual読み込むのが一番。書いてないのは本家と比べて合うように作っていくしかないかな。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次