【C言語】
既にある標準関数を自作するな
(車輪の劣化再発明)

標準関数を 自作するな

warning: conflicting types for built-in function ‘memcpy’;

警告:組み込み関数 ‘memcpy’ の型の不一致
[-Wbuiltin-declaration-mismatch]


■パチモノ関数を実務で作ってはいけない

あなたが天才でない限り以下3点で
あなたの自作パチモノ関数は、
コンパイラ提供の標準関数に勝てません。

(1)プログラムの処理速度
(2)プログラムのメモリサイズ
(3)プログラムの品質

■標準関数を自分で宣言してはいけない

typedef unsigned char   U1 ;
typedef unsigned short  U2 ;
typedef void            VD ;

//ダメ:標準関数を自分で宣言する
//  ->コンパイラから提供されるヘッダファイルを使いましょう
VD  memcpy(U1 *dst,U1 *src,U1 size) ;

標準関数のプロトタイプ宣言を自分で書いてはいけません。
コンパイラから提供されているヘッダファイルを使いましょう。


■標準関数を自分で定義してはいけない

//ダメ:標準関数を自分で作る(車輪の発明)
//  ->コンパイラから提供される標準関数を使いましょう
VD  my_memcpy(U1 *dst,U1 *src,U1 size)
{
    ;//既にある物を自分で作ってはいけません
  for(UI i = 0 ; i < size ; i;;){
       dst[i] = src[i];
    }
}

標準関数の関数定義をわざわざ自分で書いて
製品出荷するのは止めましょう。
コンパイラから提供されたライブラリを使いましょう。


■パチモノ関数のバグは検出困難

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