warning: conflicting types for built-in function ‘memcpy’;
警告:組み込み関数 ‘memcpy’ の型の不一致
[-Wbuiltin-declaration-mismatch]
■この記事の概要
この記事では、C言語で標準関数の自作を避けるべき理由を解説し、標準ライブラリ使用による効率と安全性の重要性を紹介します。
パフォーマンス低下やバグのリスクを避けるため、標準関数の活用が推奨されています。
■標準関数を自分で作ってはいけない
あなたが天才でない限り以下3点で
あなたの自作関数は、
コンパイラ提供の標準関数に勝てません。
(1)プログラムの処理速度
(2)プログラムのメモリサイズ
(3)プログラムの品質
//ダメ:標準関数を自分で作る(車輪の発明)
// ->コンパイラから提供される標準関数を使いましょう
VD my_memcpy(U1 *dst,U1 *src,U1 size)
{
;//既にある物を自分で作ってはいけません
for(UI i = 0 ; i < size ; i;;){
dst[i] = src[i];
}
}
標準関数をわざわざ自分で書いて
製品出荷するのは止めましょう。
コンパイラから提供されたライブラリを使いましょう。
■標準関数を自分で宣言してはいけない
typedef unsigned char U1 ;
typedef unsigned short U2 ;
typedef void VD ;
//ダメ:標準関数を自分で宣言する
// ->コンパイラから提供されるヘッダファイルを使いましょう
VD memcpy(U1 *dst,U1 *src,U1 size) ;
標準関数のプロトタイプ宣言を自分で書いてはいけません。
コンパイラから提供されているヘッダファイルを使いましょう。
■自作関数のバグは検出困難
U2 src[2048] ;
int main(void)
{
U2 dst[1024];
//問題1:標準関数と型が微妙に違う
//問題2:キャストだらけになる
//問題3:メモリ破壊を検出できなくなる(dst size < src size)
//問題4:切り捨てが発生する(U1 < sizeof(src))
my_memcpy((U1 *)dst,(U1 *)src,sizeof(src));
}
strcpy(),strcmp(),strcat(),memcpy(),memcmp()、memset()など
既に標準関数としてコンパイラから提供されている標準関数を
再度自分で作って製品出荷するのは止めましょう。
現代のコンパイラや静的解析ツールは標準関数の使い方誤りを見つけてくれますが自作した関数ではコンパイラが関数仕様を知らないので
問題検出が困難になります。
■自作関数のよくあるバグ
#include <stdio.h>
#include <stdint.h>
static inline void START(const char *funcname){
fprintf(stderr,"%s\n",funcname);
fflush(stderr);
}
void *memset8(uint8_t *s,int c,size_t n){
START(__func__);
for(size_t i = 0;i < n;i++){
s[i] = (uint8_t)c ;
}
return s;
}
void *memset16(uint16_t *s,int c,size_t n){
START(__func__);
for(size_t i = 0;i < n;i++){
s[i] = (uint16_t)c ;
}
return s;
}
void *memset32(uint32_t *s,int c,size_t n){
START(__func__);
for(size_t i = 0;i < n;i++){
s[i] = (uint32_t)c ;
}
return s;
}
int main(void){
uint8_t buf8[1024];
uint16_t buf16[1024];
uint32_t buf32[1024];
memset8(buf8, 0,sizeof(buf8));
memset16(buf16, 0,sizeof(buf16));
memset32(buf32, 0,sizeof(buf32));
}
memset8よりループの回転数が
memset16は半分なので、処理速度が2倍!。
memset32は1/4なので、処理速度が4倍!。
と、考えたプロジェクトで十中八九発生するバグです。
■C言語初心者の人は別、どんどん作ろう
練習用に文字列操作関数を自分で作ってみましょう。
一番簡単な
strlen()の配列版から初めて
strlen()のポインタ版を作り、
strcpy(),strcmp(),strcat(),,,,,と作っていき、
strtok()が作れた時には
ポインタがほぼ理解できていることでしょう。
参考:Cプログラマへの十戒
7.ライブラリを学び、正当な理由なく新しいものを自作しないようにせよ。
それは汝のコードを短く読みやすいものとし、
日々を快適で生産的にするためである。https://www.gfd-dennou.org/arch/comptech/cstyle/cstyle-ja.htm