web-dev-qa-db-ja.com

「バイト数」をゼロに設定してmemcpy()およびmemmove()を呼び出すことはできますか?

memmove()/memcpy()で実際に移動/コピーするものが何もない場合をEdgeケースとして扱う必要がありますか

int numberOfBytes = ...
if( numberOfBytes != 0 ) {
    memmove( dest, source, numberOfBytes );
}

またはチェックせずに関数を呼び出す必要があります

int numberOfBytes = ...
memmove( dest, source, numberOfBytes );

前のスニペットのチェックは必要ですか?

89
sharptooth

C99標準(7.21.1/2)から:

size_t nとして宣言された引数が関数の配列の長さを指定している場合、nはその関数の呼び出しで値ゼロを持つことができます。この節の特定の関数の説明で特に明記されていない限り、7.1.4。このような呼び出しでは、文字を見つける関数は出現しません。2つの文字シーケンスを比較する関数はゼロを返し、文字をコピーする関数はゼロ文字をコピーします。

したがって、答えはノーです。チェックは不要です(または、はい。ゼロを渡すことができます)。

127
Mike Seymour

@Youが言ったように、標準では、memcpyとmemmoveがこのケースを問題なく処理するように指定しています。彼らは通常、何らかの形で実装されているので

void *memcpy(void *_dst, const void *_src, size_t len)
{
    unsigned char *dst = _dst;
    const unsigned char *src = _src;
    while(len-- > 0)
        *dst++ = *src++;
    return _dst;
}

関数呼び出し以外のパフォーマンスペナルティさえも持たないでください。コンパイラがこのような関数の組み込み関数/インライン化をサポートしている場合、追加のチェックはコードを非常に遅くすることさえあります。

4
Matteo Italia