2

私は C を初めて使用します。strncpy 関数の使用に行き詰まっています。\

これが私が取り組んでいるものの例です:

int main()
{

const char *s = "how";

struct test {
    char *name;
};

struct test *t1 = malloc(sizeof(struct test));

strncpy(t1->name, s, sizeof(*s));
t1->name[NAMESIZE] = '\0';

printf("%s\n", t1->name);

}

const char * があります。test の「name」値を const char に設定する必要があります。私はこれを理解するのに本当に苦労しています。これは正しいアプローチですか?

どうもありがとうございました!

4

4 に答える 4

5

さて、構造体を割り当てますが、構造体内の文字列は割り当てません。コピーする前に、それを行う必要があります。その場合でも、文字列ターミネータを設定しようとすると、おそらく未割り当てのメモリが上書きされます。

そして、ワインの摂取量が多いため、実際には1文字しかコピーしていないことに気付きましたが、それはまだ未定義の動作です.

于 2013-02-09T19:40:35.357 に答える
3

これを 1 つずつ実行してみましょう。

struct test *t1 = malloc(sizeof(struct test));

これにより、にスペースが割り当てられstruct testます。ポインタには十分なスペースがありますが、ポインタが指すnameメモリはありません。少なくとも、次のことを行う必要があります。

t1->name = malloc(strlen(s) + 1);

それが完了したら、文字列のコピーに進むことができます。ただし、メモリを割り当てるために文字列の長さを 1 回計算しています。を呼び出して暗黙的に再度実行しても意味がありませんstrncpy。代わりに、次の操作を行います。

const size_t len = strlen(s) + 1;  // +1 accounts for terminating NUL
t1->name = malloc(len);
memcpy(t1->name, s, len);

一般に、この基本的なパターンを使用してみてください。文字列の長さは、コードに入ったときに一度計算しますがmem*、暗黙的な長さの文字列の代わりに、明示的なサイズのメモリ バッファーと操作を使用しstr*ます。適切に実行すれば、少なくとも同じくらい安全で(多くの場合、より安全です)、より効率的です。

strncpyif was a fixed-size array を代わりに使用することもできますt1->name(ただし、多くの人は を使用することを好みますstrlcpy)。それは次のようになります。

struct test { char name[MAXSIZE]; };
struct test *t1 = malloc(sizeof *t1);
strncpy(t1->name, s, MAXSIZE - 1);
t1->name[MAXSIZE-1] = 0; // force NUL-termination

sizeへの引数は、宛先バッファの境界外への書き込みを避けるために、常にソースではなく宛先strncpyのサイズである必要があることに注意してください。

于 2013-02-09T19:54:11.013 に答える
2

完全性や教育的方向性を試みることなく、これが機能するはずのコードのバージョンです。このサイトでは、「間違い探し」をプレイして、それぞれの説明を個別に検索できます。

int main()
{ 
    const char s[] = "how";                 // s is an array, const char[4]

    struct test{ char name[NAMESIZE]; };    // test::name is an array

    struct test * t1 = malloc(sizeof *t1);  // DRY

    strncpy(t1->name, s, NAMESIZE);         // size of the destination
    t1->name[NAMESIZE - 1] = '\0';          // because strncpy is evil

    printf("%s\n", t1->name);

    free(t1);                               // clean up
}
于 2013-02-09T19:50:25.207 に答える
1

strncpy() は常に間違っています

  • 結果が長すぎる場合、ターゲット文字列はヌルで終了しません
  • ターゲットが長すぎる場合 (3 番目の引数)、末尾は完全に NUL で埋められます。大きなバッファーと短い文字列がある場合、これは多くのサイクルを無駄にします。

代わりに、 memcpy() または strcpy (または、あなたの場合は strdup() ) を使用できます。

int main()
{
const char *s = "how";

struct test {
    char *name;
    };
struct test *t1
size_t len;

t1 = malloc(sizeof *t1);

#if USE_STRDUP

  t1->name = strdup(s);

#else

  len = strlen(s);
  t1->name = malloc (1+len);
  memcpy(t1->name, s, len);
  t1->name[len] = '\0';

#endif    

printf("%s\n", t1->name);

return 0;
}
于 2013-02-09T20:00:42.123 に答える