2011-08-16 13 views
6

は、これは質問からの回答をもとに質問です:私は今、違いを理解char配列VSシャア*

const char myVar* vs. const char myVar[]

const char* x = "Hello World!"; 
const char x[] = "Hello World!"; 

が、私の新しい質問は以下のとおりです。

(1)どのような私がxを再割り当てすると、最初の行の "Hello World"文字列に起こりますか?その時点でそれを指すことはありません - スコープが終了したときに破壊されるのでしょうか?

(2)2つの例の値は、定数とは別に、コンパイラによって異なるメモリにどのように格納されますか?

答えて

9

コードに"Hello World!"を配置すると、コンパイラはその文字列をコンパイルされた実行可能ファイルに含めます。プログラムが実行されると、その文字列はmainの呼び出しの前にメモリに作成され、アセンブリの呼び出し前であっても、__start(静的な初期化子が実行を開始する)の前に呼び出されます。 char * xの内容は、newまたはmalloc、またはmainのスタックフレームに割り当てられていないため、割り当てを解除することはできません。

しかし、関数またはメソッド内で宣言されたchar x[20] = "Hello World"はスタックに割り当てられ、スコープ内では実際には2つのコピーがメモリに格納されます.1つは実行可能ファイルがプリロードされ、割り当てられたバッファ。

+0

const char x []はデータをスタックにコピーすることになっています。 –

-1
  1. 正式両方の場合において"Hello World!"列がcharの連続配列としてスタティック・メモリに割り当てられていないので、再利用するためにも、任意のクラスのインスタンスを破壊するために動的に割り当てられたメモリには存在します。
  2. xは、定義されている場所に応じて、スタティックメモリまたはスタックに割り当てられます。しかし、ポインタは対応する"Hello World!"文字列を指すように初期化されますが、配列は文字列リテラルを直接その中にコピーすることによって初期化されます。

理論的にコンパイラは、文字列リテラルにアクセスする方法がない場合でも、両方の文字列リテラルのメモリを自由に再利用できます。実際には、通常は静的メモリが終了するまでプログラムに割り当てられたままであるため、最初のものは再利用される可能性は低くなります。一方、配列にスタックが割り当てられている場合は、配列が正しく初期化されていることをコンパイラが保証するために配列に割り当てられていない場合もあります。また、配列メモリがなくなると再利用されます範囲。

+0

さらに、ポインタでsizeof(x)を実行すると、4(または64ビットコードでは8)になりますが、sizeof(x)は配列に含まれるバイト数になります。 – Matthew

+2

-1:同じ方法で割り当てられていません。最初の例は、静的メモリへのポインタです。 2番目の例は非静的配列で、その内容は '' Hello world! ''で初期化されます。 –

+2

私はconst char x []の背後にある考え方は、配列が単にポインタではなくスタック上にあるということだと思うし、 "Hello World!"それにコピーされます。これは最適化されているかもしれませんが、そのアイデアは単純なポインタとはまったく異なります。 –

4

コンパイラは、最初のものをRODATA(読み取り専用データ)というメモリのセクションに格納します。プログラムがまだ実行されている限り、メモリはまだ初期値を保持しています。

2番目のスタックは他の配列と同じようにスタックに格納されます。他のローカル変数と同様に、スコープが終了すると上書きされる可能性があります。

+0

'プログラムがまだ実行されている限り、メモリはまだ初期値を保持しています。つまり、文字列のスコープはプログラムスコープであり、関数のスコープではありません。 –