文字ポインターと文字配列の使用の違い
質問
基本的な質問。
char new_str[]="";
char * newstr;
データを連結したり、strcat / substr / strcpyなどの文字列関数を使用したりする必要がある場合、2つの違いは何ですか?
char *アプローチにメモリを割り当てる必要があることを理解しています(行#2)。どうしたらいいかわかりません。
そしてconst char *と文字列リテラルは同じですか?
これについてもっと知る必要があります。誰かが素敵な網羅的なコンテンツ/素材を指すことができますか?
他のヒント
混乱を解消するための優れたソースは、エキスパートCプログラミング、Deep Cの秘密であるPeter Van der Lindenです。配列とポインターは同じではないということは、メモリ内での対処方法です。
配列の場合、
char new_str[];コンパイラは、new_strに、コンパイル時と実行時の両方で既知のメモリアドレスを与えました。 0x1234。したがって、
[]
を使用することにより、new_strのインデックス付けは簡単です。たとえば、 new_str [4]
の場合、実行時にコードは new_str
が存在する場所のアドレスを選択します。 0x1234(つまり、物理メモリ内のアドレス)。インデックス指定子 [4]
を0x1234 + 0x4に追加すると、値を取得できます。
一方、コンパイラは、ポインタを使用して、シンボル
char *newstrにアドレスを与えます。 0x9876、しかし実行時に、使用されるそのアドレスは間接アドレス指定スキームです。 newstrがmalloc'd
newstr = malloc(10);されたと仮定すると、newstrのアドレスはコンパイラーによって認識されているため、コード内の参照がnewstrを使用するたびに行われます。つまり、0x9876が指すのはnewstrです。 。実行時に、コードは物理メモリ0x9876(つまり、newstr)からデータを取得しますが、そのアドレスは別のメモリアドレス(mallocしたため)、たとえば0x8765はここにあるため、コードはそのメモリアドレスからデータを取得しますnewstrに割り当てられたmalloc、つまり0x8765。
char new_str []
と char * newstr
は同じ意味で使用されます。これは、配列の 0番目の要素のインデックスが減衰してポインターになり、 char * newstr を宣言したにもかかわらず、
newstr [5]
または *(newstr + 5)
ポインタ式がどのように使用されるかに注意してください。 code>、したがって
*(new_str + 1)
= *newstr;
または*(new_str + 1)
= newstr[1];
要約すると、両者の本当の違いは、メモリ内でのアクセス方法です。
本を手に入れて読んで、生きて呼吸してください。その素晴らしい本! :)
これは文字配列です:
char buf [1000];
たとえば、これは意味がありません:
buf = &some_other_buf;
これは、 buf
にはタイプポインターの特性がありますが、意味のある唯一の場所を既に指しているためです。
char *ptr;
一方、 ptr
は単なるポインタであり、どこかを指している場合があります。ほとんどの場合、これは次のようなものです:
ptr = buf; // #1: point to the beginning of buf, same as &buf[0]
または多分これ:
ptr = malloc (1000); // #2: allocate heap and point to it
または:
ptr = "abcdefghijklmn"; // #3: string constant
これらのすべてについて、一部のコンパイル環境が文字列定数を書き込み不可に定義する3番目の場合を除き、* ptrに書き込むことができます。
*ptr++ = 'h'; // writes into #1: buf[0], #2: first byte of heap, or
// #3 overwrites "a"
strcpy (ptr, "ello"); // finishes writing hello and adds a NUL
違いは、一方がポインターであり、もう一方が配列であることです。たとえば、sizeof()配列を使用できます。 こちら
タグが示すようにC ++を使用している場合、C char
配列ではなく、C ++文字列を実際に使用する必要があります。
string
タイプを使用すると、文字列の操作が非常に簡単になります。
何らかの理由で char
配列でスタックしている場合、次の行:
char new_str[] = "";
は1バイトのスペースを割り当て、そこにヌルターミネーター文字を挿入します。それは微妙に異なります:
char *new_str = "";
書き込み不可能なメモリへの参照を提供する可能性があるため。ステートメント:
char *new_str;
それ自体はポインタを提供しますが、それが指すものは何も提供しません。関数に対してローカルな場合、ランダムな値を持つこともできます。
人々が(C ++ではなくCで)行う傾向があるのは、次のようなことです:
char *new_str = malloc (100); // (remember that this has to be freed) or
char new_str[100];
十分なスペースを確保します。
str ...
関数を使用する場合、すべての種類を取得しないように、基本的に char
配列に十分なスペースがあることを確認する必要がありますコードのデバッグに関する奇妙で素晴らしい練習。実際のC ++文字列を使用する場合、多くの面倒な作業が自動的に行われます。
最初の型はchar [1]、2番目はchar *です。さまざまなタイプ。
Cの malloc
、またはC ++の new
を使用して、後者にメモリを割り当てます。
char foo[] = "Bar"; // Allocates 4 bytes and fills them with
// 'B', 'a', 'r', '\0'.
ここでのサイズは、初期化文字列から暗示されています。
foo
の内容は変更可能です。たとえば、 i
= 0..3。
foo [i]
を変更できます。
OTOHの場合:
char *foo = "Bar";
コンパイラは、静的な文字列" Bar"を割り当てます。読み取り専用メモリにあり、変更できません。
foo[i] = 'X'; // is now undefined.
char new_str[]="abcd";
これは、サイズが5バイトの文字の配列(文字列)を指定します(各文字に1バイトとヌルターミネータに1バイト)。したがって、文字列「abcd」をメモリに保存し、変数new_strを使用してこの文字列にアクセスできます。
char *new_str="abcd";
これは、文字列「abcd」がメモリのどこかに保存され、ポインターnew_strがその文字列の最初の文字を指すことを指定します。
メモリ割り当て側でそれらを区別するには:
// With char array, "hello" is allocated on stack
char s[] = "hello";
// With char pointer, "hello" is stored in the read-only data segment in C++'s memory layout.
char *s = "hello";
// To allocate a string on heap, malloc 6 bytes, due to a NUL byte in the end
char *s = malloc(6);
s = "hello";
C ++を使用している場合、 std :: string を使用しない理由すべての文字列が必要ですか?特に、連結を扱うもの。これは多くの問題からあなたを救います。