4

これはやや無意味かもしれませんが、皆さんがそれについてどう思うか興味があります。ポインターを使用して文字列を反復処理していて、そこから短い部分文字列を引き出したい(部分文字列を事前に割り当てられた一時配列に配置する)。strncopyよりも割り当てを使用する理由はありますか?またはその逆ですか?つまり

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{   char orig[]  = "Hello. I am looking for Molly.";

    /* Strings to store the copies
     * Pretend that strings had some prior value, ensure null-termination */
    char cpy1[4] = "huh\0";
    char cpy2[4] = "huh\0";

    /* Pointer to simulate iteration over a string */
    char *startptr = orig + 2;
    int length = 3;
    int i;

    /* Using strncopy */
    strncpy(cpy1, startptr, length);

    /* Using assignment operator */
    for (i = 0; i < length; i++)
    {   cpy2[i] = *(startptr + i); 
    }   

    /* Display Results */
    printf("strncpy result:\n");
    printf("%s\n\n", cpy1);
    printf("loop result:\n");
    printf("%s\n", cpy2);
}   

strncopyはタイピングが少なく、読みやすいように思えますが、代わりにループを提唱する人を見てきました。違いはありますか?それも重要ですか?これはiの値が小さい場合(0 <i <5)であり、ヌル終了が保証されていると想定します。

参照:cの文字列、subStringの取得方法、Cの部分文字列の取得方法strncpyとmemcpyの違いは?

4

4 に答える 4

4

strncpy(char * dst, char *src, size_t len)2つの特有の特性があります:

  • if (strlen(src) >= len):結果の文字列はヌル文字で終了しません。
  • if (strlen(src) < len):文字列の末尾は「\0」で埋められます。

最初のプロパティでは、実際に確認して(strlen(src) >= len)適切に動作するように強制されます。(または、@ Gillesが上記で行ったように、残酷に最後の文字をnulに設定dst[len-1] = '\0';します)他のプロパティは特に危険ではありませんが、多くのサイクルをこぼす可能性があります。想像:

char buff[10000];
strncpy(buff, "Hello!", sizeof buff);

これは10000バイトに触れ、7つだけに触れる必要があります。

私のアドバイス:

  • A:サイズがわかっている場合は、memcpy(dst,src,len); dst[len] = 0;
  • B:サイズがわからない場合は、なんらかの方法で取得してください(strlenおよび/またはsizeofおよび/または動的に割り当てられたメモリに割り当てられたサイズを使用して)。次に、上記のAに移動します。

安全な操作のために、strncpy()バージョンはすでにサイズ(およびそれらのチェック!)を知っている必要があるため、memcpy()バージョンはstrncpy()バージョンよりも複雑でも危険でもありません。(技術的には、わずかに高速です。memcpy()は'\ 0'バイトをチェックする必要がないため)

于 2012-09-05T15:24:06.277 に答える
3

これは直感に反しているように見えるかもしれませんが、ループで代入演算子を使用するよりも、文字列をコピーするためのより最適化された方法があります。たとえば、IA-32は、文字列処理のために、などのREPプレフィックスを提供します。これらは、一度に1文字をコピーするループよりもはるかに高速です。より良いパフォーマンスを達成するために、そのようなハードウェア最適化コードの実装または使用を選択する場合があります。MOVSSTOSCMPSstrncpystrcpy

于 2012-09-05T14:29:06.950 に答える
1

あなたの長さが「範囲内」であり、すべてが正しくnulで終了していることがわかっている限り、それstrncpyはより良いことです。

そこに長さチェックなどを入れる必要がある場合は、ループの方が便利かもしれません。

于 2012-09-05T14:29:05.800 に答える
0

車輪の再発明をしているので、割り当てのあるループは悪い考えです。間違いを犯す可能性があり、コードは標準ライブラリのコードよりも効率が悪い可能性があります(一部のプロセッサにはメモリコピー用の最適化された命令があり、最適化された実装では通常、可能であれば少なくとも単語ごとにコピーします)。

ただし、これstrncpyは丸みのあるホイールではないことに注意してください。特に、文字列が長すぎる場合、宛先にヌルバイトを追加しません。BSD関数strlcpyはより適切に設計されていますが、どこでも利用できるわけではありません。strlcpy 万能薬ではありません。バッファサイズを正しく取得する必要があり、文字列が切り捨てられる可能性があることに注意してください。

文字列が長すぎる場合は切り捨てを使用して文字列をコピーする移植可能な方法はstrncpy、終了するnullバイトを呼び出して常に追加することです。バッファが配列の場合:

char buffer[BUFFER_SIZE];
strncpy(buffer, source, sizeof(buffer)-1);
buf[sizeof(buffer)-1] = 0;

バッファがポインタとサイズで指定されている場合:

strncpy(buf, source, buffer_size-1);
buf[buffer_size-1] = 0;
于 2012-09-05T14:38:19.310 に答える