ポインタの配列の仕組みについて、非常に誤解があります。それはポインタをメモリに保持し、メモリ自体は保持しません。これは、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_mem
をp_msglist[0]
に保存し、msg_mem + 16
をp_msglist[1]
に保存し、msg_mem + 32
をp_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であります...
'p_msglist'に格納されているポインタのターゲットが常に' p_msglist'に関連付けられ、常に16バイトになる場合、多次元配列( 'char p_msglist [3] [ 16]; ')ポインタ配列ではありません。ポインタ配列は、ポインターが何を指しているのか、そのストレージを誰が管理しているのかは気にしません。 – PSkocik
"charポインタが8バイトを保持していることを知っています"いいえ、 'char *' *は8バイトかもしれません。また、たいていは4バイトです。それとも、まったく別のものかもしれません。 –
はい私も知っている:)私は私の場合は8バイトであることを意味した。しかし、あなたは正しいと思います。 –