2017-11-09 5 views
0

私は例を挙げて説明しようとします:文字列の配列のメモリサイズを取得するには?

レッツは、このリスト内の各メッセージは固定に格納されなければならない3.

char* p_msglist[3]; 

、私は固定数でメッセージリストを作成したいと言いますサイズ(例えば、各メッセージが16バイトのメモリ、合計48バイトを保持するように、16文字。 チャーこと

16 //size of msg is ok. 
24 

私が知っている:

p_msglist[0] = msg; 
p_msglist[1] = msg2; 
p_msglist[2] = msg3; 
printf("%lu\n", sizeof(msg)); 
printf("%lu\n", sizeof(p_msglist)); 

出力:リスト内のこれらのメッセージのそれぞれをポインティングした後、私はsizeof最初のメッセージとリストを印刷

char msg[16] = "first message"; 
char msg2[16] = "second message"; 
char msg3[16] = "third message"; 

ポインタは8バイトを保持し、メッセージリストは3要素で初期化され、最後の行は2を出力します4.私が聞きたい:

  • 私のリストは3*16=48バイトを保持していることを取得する方法があります。私のリストが48バイトのメモリを保持していることを確かめることができますか?

  • メモリ(mallocなど)を割り当てたい場合は、リストのポインタとリスト自体(24バイト+ 48バイト)を気にする必要がありますか?

ありがとうございます。

+1

'p_msglist'に格納されているポインタのターゲットが常に' p_msglist'に関連付けられ、常に16バイトになる場合、多次元配列( 'char p_msglist [3] [ 16]; ')ポインタ配列ではありません。ポインタ配列は、ポインターが何を指しているのか、そのストレージを誰が管理しているのかは気にしません。 – PSkocik

+1

"charポインタが8バイトを保持していることを知っています"いいえ、 'char *' *は8バイトかもしれません。また、たいていは4バイトです。それとも、まったく別のものかもしれません。 –

+0

はい私も知っている:)私は私の場合は8バイトであることを意味した。しかし、あなたは正しいと思います。 –

答えて

1

ポインタの配列の仕組みについて、非常に誤解があります。それはポインタをメモリに保持し、メモリ自体は保持しません。これは、3つのポインタの配列です

char* p_msglist[3]; 

(それはあなたがp_msglistを宣言した時点で、メッセージのサイズがまだ知られていなかったからである。それを行うことはできません)。これらのポインタのそれぞれはアドレスを意味します。アドレスは通常、32ビットまたは64ビットのいずれか大きいです(ただし、すべてのハードウェアにはありません)。それはそれぞれ4または8バイトです。

あなたは64ビットマシンで作業しているので、3つのポインタの配列は3 x 8 = 24バイトです。今、重要なポイントに

3つのポインタのそれぞれは、いくつかの異なるアドレスを指すことができます。あなたの3つのメッセージが記憶の中でお互いにあっても必要なことは何も保証されていません。指示されたメッセージのメモリはではなく、sizeof p_msglistに含まれています。

あなたは全体p_msglistのメッセージをメモリをmallocしたい場合は、あなたがしなければならない:

  • p_msglistのための24のバイトを割り当てます。
  • のメッセージごとに16バイトを割り当てて、そのメッセージのアドレスをそれぞれp_msglistの要素に格納します。
  • 再びメモリを解放するとき、あなたは(すなわち、 free(p_msglist[0])free(p_msglist[1])free(p_msglist[2]))各メッセージに free()を呼び出す必要があります

free(p_msglist)そのもの。 (重要:最初にメッセージを解放するには、、次には配列を解放します)。

メッセージがメモリ内で連続しているようにするには、3 * 16 =メッセージの場合は48バイト(msg_memに保存してください)、msg_memp_msglist[0]に保存し、msg_mem + 16p_msglist[1]に保存し、msg_mem + 32p_msglist[2]に保存します。

そのを解放し、あなたなければならない唯一のp_msglist[0]上の個々のメッセージではないコールfree()、(とp_msglist、あなたは動的にそのためのメモリを割り当てられている場合)。割り当て関数の1つから以前に取得したのと全く同じアドレスにfree()を呼び出すだけです。あなたが連続し、割り当てられたメモリにメッセージp_msglistを持っているしたい場合は、メモリの48 + 24 = 72バイト(sizeof(p_msglist) + sizeof(msg) + sizeof(msg2) + sizeof(msg3))を割り当てなければならないだろう

...そしてもちろんのみfree(p_msglist)その後。


あなたはすべてのmallocにメモリをしたいと、まだメモリが1つのブロックにしたくない場合は、あなたが宣言することができます...

char p_msglist[3][16] = { { "first message" }, { "second message" }, { "third message" } }; 

これは、二を割り当てます3 x 16文字の3次元配列で、指示に従って初期化します。しかし、もちろんこれはローカルオブジェクトのみで、他のローカル変数と同じように範囲外になります(動的に割り当てられたメモリとは反対に、free()まで有効です)。

後者の構築物についての「面白い」ものはp_msglist代わり個々アレイに3つのポインタを保持する「直接」の二次元アレイであるので、この場合sizeof p_msglistが、実際には、3×16 = 48であります...

+0

このような説明のお返事ありがとう:) –

+0

@ErselEr:私は、指針を "取得"する前に、自分自身を置かなければならなかった精神的歪曲を覚えています。元々の時代に戻ってきました...私は、誰かがあなたを軌道に乗せて、あなたに少しのプッシュを与える人がいます。 ;-) – DevSolar

+0

うん、そうです。もう一度ありがとう:) Btw、私はちょうど積極的な方法でstackoverflowを使用し始めたと私は非常にあなたのおかげで感謝しています –

2

最初の質問に対する回答はいいえです。ポインタ自体からサイズを取得することはできません。

依存: -

  1. をあなたがそれらのchar*年代を割り当てたい場合は[はい、あなたが考慮する必要があります。

  2. 3を持つことが十分であると確信できる場合は、char*を入力してください。noを考慮する必要はありません。

いずれの場合も、文字列を格納するメモリを割り当てる必要があります。たとえば、ここでは16文字のスペースを割り当てます。

(または単に文字列リテラルに割り当てます)。

関連する問題