temp2
ととはどう違いますか はどう違いますtemp3
か
node* temp2 = head;
node** temp3 = &head;
ポインターへのポインターとポインターの違いは何ですか
実際には両方のポインタは同じです: メモリに格納されたメモリ位置。それらは、それらが指すメモリ位置に格納されているものだけが異なります。
プログラマーの観点から見ると、コンピューターのメモリはペアのリストと考えることができます。
名前付きの各オブジェクト/変数name
は、
name
)&name
)したがって、メモリ値/アドレスのペアの 1 つです。
例
node
(簡単にするために)が整数型であると仮定しましょう。head
値で定義すると631
:
node head = 631;
特定のメモリ位置 (つまり0x002
) が選択され (コンパイラがオフセットを選択し、OS がメモリ内の最終位置を指示します)、値631
がその位置に格納されます。
---------------------------------- | | 住所 | | ヴァル | 名前 | ---------------------------------- | | 0x002 | 631 | 頭 | ----------------------------------
head
現在 (そして唯一) は、特定のメモリ位置 (0x002
この例では) の値のエイリアスまたは名前です。
ポインターを定義すると、何も変わりません。
node* temp2 = &head; // &head == 0x002
再びメモリ位置が選択され (すなわち0x005
)、値 ( 0x002
) がその位置に格納されます。
---------------------------------- | | 住所 | | ヴァル | 名前 | ---------------------------------- | | 0x005 | 0x002 | temp2 | ----------------------------------
また、変数名temp2
は、に格納されている値の単なるエイリアスです0x005
。
また同じtemp3
です。
node** temp3 = &temp2; // &temp2 == 0x002
対応するアドレス/値のペア:
---------------------------------- | | 住所 | | ヴァル | 名前 | ---------------------------------- | | 0x007 | 0x005 | temp3 | ----------------------------------
このコードのメモリ レイアウト
node head = 631;
node* temp2 = &head;
node** temp3 = &temp2;
現在の例では次のようになります。
これをポインターに関する中途半端な包括的な答えに変えるために、 と を簡単に見てみましょ&
う*
。
すでに書いたように、それぞれName
は値/アドレスのペアを表します。
---------------------------------- | | 住所 | | ヴァル | 名前 | ----------------------------------
特定の名前に適用することに&
した場合、値/アドレスのペアのアドレスを取得します。つまり:
&temp3 == 0x007
代わりに適用*
すると、これは現在の値に対応するアドレスに格納されているもののエイリアスになります。
*temp3
意味: "の値に格納されているアドレスに格納されているものは何でも教えてくださいtemp3
" したがって、ここには 2 つのステップがあります。
temp3
覚えて:
---------------------------------- | | 住所 | | ヴァル | 名前 | ---------------------------------- | | 0x005 | 0x002 | temp2 | ---------------------------------- | | 0x007 | 0x005 | temp3 | ----------------------------------
temp3
」は0x005
です。0x005
はtemp2
.したがって
*temp3 == temp2 // temp2 is the dereferenced value of temp3
以来
temp3 == &temp2 // value of temp3 is address of temp2
ご覧のとおり: Dereferencing ( *
) は、 address-of の準反対です&
。
注:*
宣言では、ポインターを宣言し、アドレスを逆参照する演算子ではありません。
どのポインタもメモリのアドレスを保持し、このアドレスを保持するために (32 ビット システムでは) ほとんど 4 バイトのメモリが必要です。この定義に従って、ポインターへのポインターを次のように定義できます。
pointer to pointer
: メモリの別の場所のアドレスを保持する別のメモリ場所のアドレスを保持するメモリ内の 4 バイト
ここで、temp2 と temp3 を次のように定義できます。
temp2
:オブジェクトのアドレスを保持するメモリ内の場所。node
(ほとんどの場合、32 ビット システムのすべてのアドレスには 4 バイトのメモリが必要です)。このアドレスはhead
オブジェクト コンテンツと同等です。
temp3
node
: メモリ内のオブジェクトへのポインタのアドレスを保持するメモリ内の場所。このノードへのnode
ポインタはポインタとして定義できます。
したがって、temp3 はヘッド ノードのアドレスのアドレスを保持します。また、head
変数の型が単一のアドレス&
であるため、変数のアドレスを取得する演算子が必要head
です。
ポインターは、リストなどのデータ構造のメモリ位置を格納します。ポインタへのポインタは、ポインタのメモリ位置を格納します。リストの先頭を取得するには、追加の逆参照が必要になります。したがって、 no temp2 と temp3 の両方が頭を指しているわけではありません。temp2 は head が指す場所を指し、temp3 は head ポインターのメモリ位置を指します。
ポインターは、変数のアドレスを保持する変数です。
次のように宣言できます。
char *a;
そして、次のような変数のアドレスを割り当てることができます:
char b='r';
このような :
a=&b;
ポインターへのポインターは、ポインターのアドレスを保持する変数でもあります (任意の変数のアドレスを保持する変数)。
次のように宣言します。
char **c;
そして、次のa
ように、ポインタのアドレスを割り当てることができます:
c=&a;
c
b のアドレスを含むアドレスが含まれているためa
、後で a を使用して逆参照できます。**
この簡単な例によって、これら 2 つのステートメントが何を意味するかを理解できます。幸運を !!
できるよ
*temp3 = new_head;
しかし
*temp2 = new_head;
動作しません
関数などに役立ちます
void make_list(Node ** head) {
*head = malloc(sizeof(Node);
}