strncpyははまりやすい

strncpyは結構はまりどころがあります。

たとえば以下のコードは正しく動作しません。

char str[100];
const char * c = "test";
strncpy(str, c, strlen(c));
printf("%s\n", str);

strncpyはコピー先、コピー元、コピー長を引数で取ります。
この際、strlen等でコピー元の文字長ぴったりを指定すると、
終端文字がコピー先にコピーされません。

そのため、事前に終端文字を設定しておかないと、
未初期化の部分まで文字列扱いになります。

以下のコードでその様子をうかがえます。

#include <string>
#include <stdio.h>

int main(void){
  char str[100] = {0};
  str[0] = 'z';
  str[1] = 'z';
  str[2] = 'z';
  str[3] = 'z';
  str[4] = 'z';

  const char * c = "test";
  strncpy(str, c, strlen(c));

  printf("%s\nlength %lu\noriginal length %lu\n", str, strlen(str), strlen(c));

  strcat(str, ".txt");
  printf("%s\nlength %lu\n", str, strlen(str));

  return 0;
}
testz
length 5
original length 4
testz.txt
length 9

testという文字列をコピーし、.txtという文字列を追加して、
test.txt作る予定が、間に他の値が入っています。

strcatは第一引数の文字列の終わりに第二引数をつなげます。
そのため、コピー時に終端文字を設定していなかったため、
意図しない文字が間に挟まっています。
特にバッファの初期化を忘れていた場合、終端文字がいつ現れるか確定しないため、
注意が必要です。

この挙動は文字列の間に置換する場合には重宝しますが、
文字列結合などをする場合は気をつける必要があります。