warning: ‘strncpy’ output truncated before terminating nul copying 8 bytes from a string of the same length
警告:「strncpy」出力は、
第三引数と同じ長さの文字列から
8バイトをコピーして
終端文字\0を出力する前に切り捨てられました
[-Wstringop-truncation]
■この記事の概要
C言語でstrncpy
関数使用時の終端文字エラー対策として、C99構造体の指示初期化子を推奨する方法として解説します。
メモリ確保や警告回避の方法を詳述し、strncpy
の限界と代替案について学べます。
■strcpy(dsname)で警告が出る例
#include <string.h>
#include <stdio.h>
typedef unsigned char UB ;
struct ctsk {
int foo,bar,baz ;
UB dsname[8];
} ;
void cre_tsk(struct ctsk *p){
printf("dsname=%.8s\n",p->dsname);
}
int main(void){
struct ctsk x ;
x.foo = 1;
x.bar = 2;
x.baz = 3;
strncpy(x.dsname,"12345678",8) ;
cre_tsk(&x);
}
UB dsname[8]の設定でピッタリ8文字設定したいとき、
strncpy()を使用すると終端文字\0が出力に設定されないと
gcc -Wall で警告されます。
■C89構造体初期化を使った修正例
#include <string.h>
#include <stdio.h>
typedef unsigned char UB ;
struct ctsk {
int foo,bar,baz ;
UB dsname[8];
} ;
void cre_tsk(struct ctsk *p){
printf("dsname=%.8s\n",p->dsname);
}
int main(void){
struct ctsk x ={
1,
2,
3,
"12345678"
} ;
cre_tsk(&x);
}
C89仕様の古いC言語では上記のように
構造体の宣言と同時に初期化すると
strncpy()を使用する必要がないので警告は消えますが
どのメンバを初期化しているのかわかりにくいといった欠点があります。
■C99指示初期化子を使った修正例
#include <string.h>
#include <stdio.h>
typedef unsigned char UB ;
struct ctsk {
int foo,bar,baz ;
UB dsname[8];
} ;
void cre_tsk(struct ctsk *p){
printf("dsname=%.8s\n",p->dsname);
}
int main(void){
struct ctsk x ={
.foo=1,
.bar=2,
.baz=3,
.dsname="12345678"
} ;
cre_tsk(&x);
}
C99仕様のC言語では上記のように構造体の宣言時に指示初期化子が使えます。
strncpy()を使用する必要がないので警告は消え、
どのメンバを初期化しているのか明確にわかります。
■注意事項
dsname に終端文字\0 が無い場合はdsnameは文字列ではないので
strlen(x.dsname)とか
strcpy(dst,x.dsname)とか
文字列操作関数を使用すると終端文字\0を見つけられずに
暴走する可能性があります。
参考:
プログラミング言語 C の新機能
http://seclan.dll.jp/c99d/