1

以下は、C の文字列に関していくつかの基本的な質問です。

  • 文字列リテラルが読み取り専用データ セグメントに格納され、初期化後に変更できない場合、次の 2 つの初期化の違いは何ですか

char *string = "こんにちは世界";

const char *string = "Hello world";

  • 文字列にメモリを動的に割り当てると、次の割り当ては任意の長さの文字列を保持するのに十分な能力があることがわかります.データ型のサイズ。文字列の動的割り当ての適切な使用方法についてガイドしてください

char *str = (char *)malloc(sizeof(char));

scanf("%s",str);

printf("%s\n",str);

4

7 に答える 7

2

1.次の 2 つの初期化の違いは何ですか。 違いは、他の人がすでにこれについて語ったように、エラーのコンパイルと実行時チェックです。

char *string = "こんにちは世界"; ---> 読み取り専用データ セグメントに格納され、変更できませんが、値を変更してもコンパイラはエラーを出さず、実行時にのみ発生します。

const char *string = "Hello world"; --->これは、const として宣言されているため、コンパイル時にチェックされる読み取り専用データ セグメントにも格納されるため、文字列の値を変更すると、コンパイル時にエラーが発生します。実行時の失敗。

2.文字列の動的割り当ての適切な使用方法を教えてください。

 char *str = (char *)malloc(sizeof(char));
 scanf("%s",str);
 printf("%s\n",str);

このコードは、しばらくの間は機能する可能性がありますが、常に機能するとは限りません。プログラムが所有していないにアクセスしているため、 が発生しrun-timeたときに問題が発生します。非常に危険な.segmentation faultarea of memorydynamic memory allocationerror at run time

あなたは常にすべきallocate the amount of memory you need correctlyです。ほとんどのエラーは、割り当て中に発生します。そこと割り当て中にuse of string常に心に留めておく必要があります。is a '\0' character present at last of the stringyour responsibility to allocate memory for this.

お役に立てれば。

于 2012-10-05T10:43:13.220 に答える
1

最初のケースでは、を明示的に1にキャストしchar*ていconstます。つまり、コンパイラレベルで、その背後にある文字への変更を許可していません。Cでは、定数に関係なくこれらの文字を変更しようとするのは(実行時の)実際には未定義の動作ですが、文字列リテラルでありchar *、ではありませんconst char *

2番目のケースでは、2つの問題があります。

1つ目は、特定のエラーをマスクする可能性があるため、からの戻り値をキャストしないでくださいmalloc(特に、ポインターと整数のサイズが異なるシステムでは)。具体的には、アクティブなプロトタイプが配置されていない限り、コンパイラは、正しいプロトタイプではなく、mallocを返すと見なす場合があります。intvoid *

したがって、を含めるstdlib.hのを忘れると、コンパイラが警告できないおかしな動作が発生する可能性があります。これは、自分が何をしているかを知っていることを明示的なキャストで伝えたためです。

void *Cは、 returnedfrommallocと他のポインタ型の間で暗黙的にキャストすることができます。

2番目の問題は、1つの文字にのみスペースを割り当てることです。これは、文字列の終了nullになります。

次のように書く方がよいでしょう。

char *string = malloc (max_str_size + 1);

(そして、これを掛けないでくださいsizeof(char)、それは時間の無駄です-それは常に1です)。

于 2012-10-05T09:37:12.773 に答える
1

2 つの宣言の違いは、const char*宣言されたポインターを介して文字列リテラルを変更しようとすると、コンパイラーがエラーを生成することです (実行時エラーよりもはるかに好ましい)。次のコード:

const char* s = "hello"; /* 's' is a pointer to 'const char'. */
*s = 'a';

VC2010 で次のエラーが発生します。

エラー C2166: 左辺値が const オブジェクトを指定しています

宣言されたポインターを介して作成された文字列リテラルを変更しようとしても、char*実行時まで検出されず (VC2010 はエラーを発行しません)、その動作は未定義です。

malloc()文字列を格納するためにメモリを使用する場合は、すべて (またはほぼすべて) の C 文字列処理関数が null ターミネータを必要charとするため、null ターミネータを格納するために余分に 1 つ割り当てることを忘れないでください。たとえば、格納用のバッファを割り当てるには"hello":

char* p = malloc(6); /* 5 for "hello" and 1 for null terminator. */

sizeof(char)は 1 であることが保証されているため不要であり、 の戻り値をキャストする必要はありませんmalloc()pが不要になった場合はfree()、割り当てられたメモリを覚えておいてください。

free(p);
于 2012-10-05T09:36:16.847 に答える
1

次の 2 つの初期化の違い。

まず、char *string = "Hello world";
- "Hello world" はスタック セグメントに定数文字列として格納され、そのアドレスはポインタ'string' 変数に割り当てられます。
「こんにちは世界」は一定です。また、string[5]='g' を実行することはできません。これを実行すると、セグメンテーション エラーが発生します。
「文字列」変数自体は定数ではありません。そして、そのバインディングを変更することができます:
string= "Some other string"; // これは正しく、セグメンテーション違反はありません

const char *string = "Hello world";
ここでも、「Hello world」は定数文字列としてスタック セグメントに格納され、そのアドレスは「string」変数に割り当てられます。また、string[5]='g' であり、これによりセグメンテーション違反が発生します。
ここでは const キーワードを使用しないでください。

さて、
char *string = (char *)malloc(sizeof(char));

上記の宣言は最初のものと同じですが、今回は割り当てはヒープセグメントから動的です(スタックからではありません)

于 2012-10-05T09:41:50.553 に答える
1

次の 2 つの初期化の違いは何ですか。

文字列リテラルにはchar*、従来の理由から型があります。const char*それらを変更することは許可されていないため、経由でのみ指定することをお勧めします。

次の割り当ては、任意の長さの文字列を保持するのに十分な能力があることがわかります。

違う。この割り当てでは、1 つの文字に対してのみメモリが割り当てられます。に複数のバイトを書き込もうとするとstring、バッファ オーバーフローが発生します。

メモリを動的に割り当てる適切な方法は次のとおりです。

char *string = malloc(your_desired_max_length);

ここでは明示的なキャストは冗長でありsizeof(char)、定義により 1 です。

また、文字列ターミネータ (0) も文字列に収まる必要があることに注意してください。

于 2012-10-05T09:34:08.173 に答える
0

プログラム ヒープにはおそらく十分なスペースがあるため、その特定の割り当ては機能しているように見えるかもしれませんが、そうではありません。提案された方法で2つの「任意の」文字列を割り当て、対応するアドレスに十分な長さの文字列を memcpy:ing することで確認できます。最良の場合はガベージが表示され、最悪の場合はセグメンテーション違反が発生するか、malloc または free からアサートされます。

于 2012-10-05T09:35:03.443 に答える
0

コード:

char *string = (char *)malloc(sizeof(char));

任意の長さの文字列を保持しません。単一の文字を割り当て、char 文字へのポインターを返します。文字へのポインタと文字列と呼ばれるものへのポインタは同じものであることに注意してください。

文字列にスペースを割り当てるには、次のようにする必要があります。

char *data="Hello, world";
char *copy=(char*)malloc(strlen(data)+1);
strcpy(copy,data);

malloc割り当てるバイト数を正確に伝える必要があります。+1最後に行く必要があるヌルターミネータ用です。

読み取り専用セグメントに格納されているリテラル文字列に関しては、これは実装上の問題ですが、ほとんど常にそうです。ほとんどの C コンパイラは、これらの文字列へのアクセスを const することについてかなり緩和していますが、それらを変更しようとするとconst char *問題が発生するため、問題を回避するために常に宣言する必要があります。

于 2012-10-05T09:33:32.190 に答える