2011-06-20 25 views
1

ダイナミックメモリ割り当ての概念には少し混乱があります。 ポインタがcharポインタを宣言すると、十分なメモリ空間を確保する必要があります。ダイナミックメモリ割り当て

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; 

しかし、これも機能します。

char* str = "This is a string"; 

この場合、メモリスペースを割り当てる必要がありますか?

+6

あなたの混乱は、動的メモリ割り当てではなく、ポインタに関するものです。 – ybungalobill

+0

達成しようとしていること:もう一つの選択肢があります: 'char str [] ="これは文字列です "; –

+0

なぜ' std :: string'を使わないのですか? –

答えて

1

文字列リテラルは、言語の特別なケースです。のは、このことをよく理解するためにあなたのコードをよく見てみましょう:

まず、あなたは、メモリ内のバッファを割り当て、そしてstrにそのメモリのアドレスを割り当てる:

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

その後、あなたはstrに文字列リテラルを代入します。これにより、先に保持されていたstrが上書きされるため、動的に割り当てられたバッファが失われ、メモリリークが発生します。割り当てられたバッファを変更したい場合は、ある時点でstrを参照解除する必要があります(str[0] = 'A'; str[1] = '\0';)。

str = "This is a string"; 

ここで、strの値は何ですか?コンパイラはすべての文字列リテラルを静的メモリに格納します。したがって、プログラム内のすべての文字列リテラルの存続期間は、プログラム全体の存続期間と同じです。このステートメントは、str = (char*)0x1234のような単純な割り当てにコンパイルされます。0x1234は、コンパイラが文字列リテラルを配置したアドレスであると考えられます。これがうまく機能する理由を説明し

char* str = "This is a string"; 

また、あなたがこの割り当てにconst char*を使用する必要がありますので、スタティックメモリは、実行時に変更されるものではないことに注意してください。

この場合、メモリスペースを割り当てる必要がありますか?

多くの場合、たとえば、バッファを変更する必要がある場合。言い換えると;静的な文字列定数ではないものを指す必要があるときに使用します。

+0

'char * str ="これは文字列です; "うまくいきません";それは実際には危険であり、非難されている。 –

2

最初の例では、を動的にに割り当てました。それは変更することができ、解放する必要があります。 2番目の例では、コンパイラは静的にメモリを割り当て、変更することはできず、解放してはいけません。文字列リテラルにこれを反映させて安全な使用を保証するには、char*ではなくconst char*を使用する必要があります。最初のサンプルで

7

あなたはメモリが新しい置き換えられます

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; // memory leak 

割り当てられたアドレス

をリークしています。 新しいアドレスは "This is a string"のアドレスです。

2番目のサンプルを変更する必要があります。

const char* str = "This is a string"; 

"これは文字列です"のため、書き込み禁止領域です。

+0

この場合、私は単純にできるのですが、mallocが必要です char * str = "これは文字列です"; – cppcoder

+0

これは別の質問です。 'char * str ="と書くと、これは文字列です; "あなたの文字列中の文字は変更できません。 'char * str = new char [20]'と書くと、任意のchar: 'str [13] = 'a';'を置き換えることができます。 –

+0

今、 'char * 'を修正しようとしたときに私のプログラムがクラッシュしていたのです。したがって、実際には常に 'const char *'でなければなりません。それでは 'char *'はなぜ存在するのですか? – cppcoder

1

最初の例では、間違っているだけです。動的メモリをヒープ上に割り当て、strを指すようにします。次に、strが文字列リテラルを指し、割り当てられたメモリがリークされるようにします(割り当てられたメモリに文字列をコピーしないで、アドレスstrを指すだけで、最初の例ではstrcpyを使用する必要があります) 。

1

私はあなたが次のコードのようにstrに「これは、文字列である」コピーして、最初の例のメモリリークを避けることができることを追加することによって、Alexey Malistov's Answerに追加する:であることに注意、

char* str = (char*)malloc(20*sizeof(char)); 
strcpy(str, "This is a string"); 

してください私はあなたを意味するわけではありませんを持っています。このスレッドに値を追加するための答えに追加するだけです。

+0

あなたはどのように答えの流入に追いついていますか?私は私の答えを入力し始めたときに1つの答えのようだったが、投稿後に6つの答えがあります。 –

4

おそらくC++ 98のコードスニペットは

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; 

次の処理を行い、(1)strにそのメモリブロックへのポインタを格納する、20バイトを割り当て、及び(2)は、リテラルへのポインタを格納します文字列は、strです。これで、以前に割り当てられたブロックを参照する方法がなくなり、割り当てを解除することはできません。あなたは記憶を漏らしました。

strchar*と宣言されているため、コンパイラはリテラルを変更しようとすると実際に検出できません。幸いにも、C++ 0xでははコンパイルされません。私はそのルールの変更が本当に好きです!

コードスニペット

char* str = "This is a string"; 

格納ちょうど最初の例のように、strと命名char*変数にリテラル、そしてそれはCでコンパイルしないことを例として、文字列へのポインタ++ 0xコンパイラ。

この愚かさの代わりに、標準ライブラリのstd::stringを使用し、コード全体にconstを自由に振ってください。

乾杯& HTH。、char*変数に代入

2

は、それが何か他のものを指しますので、あなたはすぐにそれを忘れている場合、なぜあなたは最初の場所でメモリを割り当てるのですか?それはメモリリークです。おそらくこれを意味します:

char* str = (char*)malloc(20*sizeof(char)); 
strcpy(str, "This is a string"); 
// ... 
free(str); 

これは、最初の文字列に2番目の文字列をコピーします。 これはC++タグ付けされているので、あなたはstd::stringを使用しないでください。

#include <string> 

std::string str = "This is a string"; 

必要な手動によるメモリの割り当てと解放を、および割り当ては、あなたがそれがない何を考えてい。