【C言語】
strNcpyとmemcpyの違いは
終端文字の扱い


■strNcmpとmemcmpが違う例

#include <stdio.h>
#include <string.h>
char s1[] = "abc\0DEF" ;    //abc+DEF
char s2[] = "abc\0XYZ" ;    //abc+XYZ
int main(void){
    if(strncmp(s1,s2,sizeof(s1)) == 0)
        printf("strncmpは'¥0'を終端とする:%sと%sは同じ\n",&s1[0],&s2[0]);
    if(memcmp(s1,s2,sizeof(s1))  != 0)
        printf("memcmpは'¥0'を終端としない:%sと%sは違う\n",&s1[4],&s2[4]);
}

●違いその1

strncmp()は終端文字¥0までしか比較しない
memcmp()は終端文字¥0を超えて比較する

●違いその2

strncmp()の第1,第2引数には char * 型しか渡せません。
(キャストしてコンパイラを騙し警告を無視するのは論外とします)
memcmp()の第1,第2引数はvoid *型なのでデータのアドレスならば
何でも渡せます。

●実行結果

strncmpは'¥0'を終端とする:abcとabcは同じ
memcmpは'¥0'を終端としない:DEFとXYZは違う


■strNcpyとmemcpyが違う例

//gcc  -g  f1.c -fsanitize=address
#include <stdio.h>
#include <string.h>
static char コピー元小[8] = "abc\0xyz";
static char コピー先大[16];         
int main(void){
    //'\0'を終端とするstr系
    strncpy(コピー先大,コピー元小,sizeof(コピー先大));
    printf("%s:%s\n",&コピー先大[0],&コピー先大[4]);

    //'\0'を終端としないmem系(バグあり)
    memcpy(コピー先大,コピー元小,sizeof(コピー先大));//★
    printf("%s:%s\n",&コピー先大[0],&コピー先大[4]);
}

●違いその1

strncpy()は終端文字¥0までしか転送しません。
memcpy()は終端文字¥0を超えて指定のサイズまで転送します。

●違いその2

第2引数が第3引数より短い場合、

strncpy()は残りを¥0で埋めます。

memcpy()は第2引数で領域外参照が発生して動作不明となります。

※このプログラムの例では転送元は8byteしかないのに16byte読み込むので領域外参照のバグとなります。
gcc -g -fsanitize=address でコンパイルすると異常終了しました。


参考:

C-FAQ 13.2:任意のバイトをコピーするときには、普通は memcpy()のほうがstrncpy()よりも適切なルーチンである。

http://www.kouno.jp/home/c_faq/c13.html#2