3

私は現在Cを学んでいますが、char配列と文字列の違い、およびそれらの動作について混乱しています。

質問1:

ソースコード1とソースコード2の結果に違いがあるのはなぜですか?

ソースコード1:

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

int main(void)
{
    char c[2]="Hi";
    printf("%d\n", strlen(c));   //returns 3 (not 2!?)
    return 0;
}

ソースコード2:

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

int main(void)
{
    char c[3]="Hi";
    printf("%d\n", strlen(c));   //returns 2 (not 3!?)
    return 0;
}

質問2:

文字列変数はchar配列とどのように異なりますか?\ 0を格納できるようにするために必要な最小限のインデックス番号でそれらを宣言するにはどうすればよいですか(以下のコードをお読みください)。

char name[index] = "Mick";   //should index be 4 or 5?

char name[index] = {'M', 'i', 'c', 'k'};   //should index be 4 or 5?

#define name "Mick"   //what is the size? Is there a \0?

質問3:

終了するNULは文字列のみをフォローし、char配列はフォローしませんか?したがって、文字列「Hi」の実際の値は[H] [i] [\ 0]であり、char配列「Hi」の実際の値は[H] [i]ですか?

質問4:

c[2]が"Hi"の後に\0を格納するとします(これがどのように行われるかわからない、gets(c)多分使用しますか?)。では、\ 0はどこに保存されますか?c[2]の後に「どこかに」保存されて[H][i]\ 0になるのか、それともc[2]に\0が追加されて[H][i][\0]になるc[3]になるのか]?

string /char配列の後に\0がある場合があり、2つの変数を比較すると問題が発生することif (c1==c2)があります。これはおそらくFALSE(0)を返すためです。

詳細な回答をいただければ幸いです。しかし、あなたの答えを簡潔にしておくことは私の理解に役立ちます:)よろしくお願いします!

4

4 に答える 4

3

回答 1 : コード 1 には、文字列ではない char 配列があります。コード 2 には、文字列でもある char 配列があります。

回答 2 : 文字列は、(少なくとも) 1 つの要素が値を持つ char 配列です0。サイズの部分を空のままにしておくと、コンパイラは自動的に可能な最小値で埋めます。

char astring[] = "foobar"; /* compiler automagically uses 7 for size */
printf("%d\n", (int)sizeof astring);

回答 3 : 要素の 1 つが文字列である char 配列NUL。要素がない char 配列はNUL文字列ではありません。

答え 4 : 2 つの要素を保持するように定義された配列 ( char c[2];) は、3 つの要素を保持できません。文字列にする場合は、空の文字列または 1 文字の文字列のみにすることができます。

于 2012-12-31T21:46:57.670 に答える
3

質問1:

ソースコード 1 とソースコード 2 の結果に違いがあるのはなぜですか?

ソースコード 1:

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

int main()
{
    char c[2]="Hi";
    printf("%d", strlen(c));   //returns 3 (not 2!?)
    getchar();
}

ソースコード 2:

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

int main()
{
    char c[3]="Hi";
    printf("%d", strlen(c));   //returns 2 (not 3!?)
    getchar();
}

answer : 最初のケースでc[]は、「こんにちは」しか保持していないためです。strlen は最後にゼロを探し、背後にあるものに応じてc[]遅かれ早かれゼロを見つけるか、クラッシュします。c[]配列の背後にあるメモリに何があるかを正確に知らなければ、何とも言えません。

質問2:

文字列変数は char 配列とどう違うのですか? \0 があれば格納できる最小の必要なインデックス番号でそれらを宣言する方法 (以下のコードを読んでください)?

char name[index] = "Mick";   //should index be 4 or 5?

char name[index] = {'M', 'i', 'c', 'k'};   //should index be 4 or 5?

答え 本当にあなたが何をしたいかによります。実際にコンテンツを文字列として使用する場合は、おそらく 5 です。しかし、「Mick」を 4 文字の配列に格納できないということは何もありません。strlen を使用してその長さを調べることはできません。なぜなら、strlen は 5 まで続き、おそらく (はるかに) さらに長さを見つけるためです。 、次のいくつかのメモリ位置にゼロがない場合、最終的に読み取る有効なメモリ アドレスがなくなるため、クラッシュにつながる可能性があります。

#define name "Mick" //what is the size? Is there a \0?

どこかで名前を使用するまで、これにはまったくサイズがありません。#defines は、コンパイラーが認識するものの一部ではありません。プリプロセッサーは、どこでも使用すると置き換えnameられます。うまくいけば、それはコンパイラーが理解できる場所にあります。そして、前の回答と同じルールが適用されます-文字の配列をどのように使用するかによって異なります。、、およびその他のほぼすべての関数を正しく操作するには、最後にゼロが必要です。"Mick"namestrlenstrpystr...

質問 3:

終端の null は文字列のみに続きますが、char 配列には続きませんか? 文字列 "Hi" の実際の値は [H][i][\0] で、文字配列 "Hi" の実際の値は [H][i] ですか?

そうですね。"Hi"それはすべて、文字列リテラル (「二重引用符で囲まれたもの」の技術的な名前) をどのように使用するかに依存します。コンパイラが「許可」されている場合は、末尾にゼロが追加されます。しかし、配列を特定のサイズに初期化すると、そこにバイトが詰め込まれます。ゼロの余地がない場合、それはあなたの問題であり、コンパイラの問題ではありません。

質問 4:

c[2] が "Hi" の後に \0 を格納しようとしているとします (これがどのように行われるかわかりません。おそらく gets(c) を使用しますか?)。では、\0 はどこに保存されているのでしょうか? c[2] の後の「どこかに」格納されて [H][i]\0 になりますか、それとも c[2] に \0 が追加されて [H][i][\0 である c[3] になりますか]?

c[2] では、「H」、「i」を超えて、何が格納されているかわかりません [技術的には、それは「地球の終わり」である可能性があります。読み取り - その場合strlen、strlen は地球の果てを超えて読み取るため、プログラムがクラッシュします].しかし、if はゼロ、1、文字 'a'、数字 42、またはその他の 8 ビットである可能性もあります[1] 値。

文字列/文字配列の後に \0 が続くことがあり、if (c1==c2) で 2 つの変数を比較すると、FALSE (0) が返される可能性が高いため、問題が発生することがあります。

c1 と c2 が char 配列の場合、c1 と c2 が同じアドレスを持つことは決してないため、これは常に false になります。C で配列をそのように使用すると、「文字列の最初の要素のメモリ内のアドレス」になります。配列"。したがって、c1 と c2 の内容が何であれ、それらのアドレスが同じになることはありません [これらは 2 つの異なる変数であり、2 つの変数がメモリ内で同じ場所を持つことはできないためです。これは、駐車スペースに 2 台の車を駐車しようとするようなものです。 1 台の車に十分な大きさ - いいえ、どちらの車も押しつぶすことは、私たちの思考実験では許可されていません]。

[1] Char は 8 ビットであることが保証されていません。しかし、今のところそれを無視しましょう。

于 2012-12-31T22:11:31.770 に答える
1

strlen()\0文字の終了に機能し、Cすべての文字列で終了する必要があり\0ます。したがって、2文字に対して2つのスペースしか指定していHないが、のスペースiがない場合\0。したがって、あなたは入ってUndefined Behaviorstrlen()ます。char c[3] = "Hi";3番目にある場合 \0、strlen()は実際の長さを計算します。

How to declare them with the minimum required index numbers allowing \0 to be stored if any ?

char配列のサイズがわからない場合は、次のようにしてください。

char c1[] = "Mike"; // strlen = 4 
char c2[] = "Omkant" // strlen = 6

ノート :

編集:サイズが明示的に言及されていない上記の場合、と混同しないでsizeofくださいstrlen()

strlen()文字数のみを返し sizeof 、文字数に1を加えた数(\0文字の場合)を返します。

したがって、sizeofは常にstrlen()によって返される数よりも正確に1多くなります。

于 2012-12-31T21:31:59.343 に答える
1

ソースコード1を実行strlen()すると、NULで終了する文字列が必要になるため、未定義の動作になりますが、そうでc[2] = "Hi"; /* = { 'H', 'i' } */はありません。文字列は、文字列が配列内のどこかに少なくとも1つのNULバイトを持つchar配列であるという点で、char配列とは異なります。

残りの答えは、この事実から簡単にたどることができます。

初期化時に文字列リテラルのサイズに一致するようにchar配列のサイズを自動化するには、配列サイズを指定しないでください。

char c[] = "This will automatically size the c array (including the NUL).";

char配列を==演算子と比較できないことに注意してください。あなたは使用する必要があります

if (strcmp(c1, c2) == 0) {
   /* Equal. */
} else {
   /* Not equal. */
}
于 2012-12-31T21:32:46.367 に答える