C/C++からアドレスを取る&の意味
2641 ワード
C言語では、&記号はきっとおなじみでしょう.
ビット単位で「AND」を演算できるほか、変数アドレスを取得する機能も一般的です.
まず、次の簡単な例を見てみましょう.
#include
int main(void)
{ int a = 0;
int *p = &a;
printf("The value is: %d/n", *p);
return 0;
}
上のコードでは、ポインタpは変数aのアドレスを指す.C/C++では、各変数に対応するアドレスがあり、変数識別子の前に&記号を付けることで変数のアドレスを得ることができます.
では、このように書いてもいいですか.int *p = &0x01000;
これは明らかにだめだ.数値定数にはアドレスがないからです.変数にアドレスがあるのは、変数を識別するメモリセルがあるからです(もちろん、変数はレジスタに直接マッピングすることもできます).
次のコードを見てみましょう.
#include "stdio.h"
int main(void)
{ int a = 0; // &a = 0x0012ff60
int *p = &*(int*)0x0012ff60; printf("The value is: %d/n", *p);
return 0; }
上のコードはどうなっていますか?
変数aのアドレスである0 x 0012 ff 60は、以前に調査されているが、ここでのポインタpも実際には変数aのアドレスを指している.
まず、0 x 001 2 ff 60をint*とし、この場合&aと等価である.
そして*(int*)0 x 0012 ff 60は、変数aをとる内容を表す.
最後に、&*(int*)0 x 012 ff 60は、再脱*(int*)0 x 012 ff 60の解参照を表し、また(int*)&aになることに相当する.
したがって,ここでの&は最初の例の&とは異なる意味である.ここの&はアドレスを取るのではなく、1つの*(int*)0 x 001 2 ff 60は変数ではなく、アドレスがありません.各変数識別子は、コンパイル中にコンパイラによってシンボルテーブルを作成し、タイプ、アドレスIDなど、変数識別子に対応するさまざまな属性が格納されます.アドレスIDは、接続後に論理アドレス値を決定します.簡単に言えば、&はアドレス取得動作として動作し、&の後に変数または関数識別子が続く場合にのみ動作する.だからここの&は引用を解くことを表します.
これにより,&アドレス取得操作としての動作結果はコンパイル時に決定される;一方、*は、参照解除操作(またはコンテンツの取得)操作であり、その動作結果は実行時にのみ決定されます.
次の例を見て、印象を深めます.
#include "stdio.h"
int main(void) {
int a = 0;
int *p = &*&*&a;
printf("The value is: %d/n", *p);
return 0; }
ただし、&シンボルは解参照*のように複数回使用できません.変数識別子または1回の解参照の前にしか配置できません.次に例を挙げる
1回&を介して参照を解除すると、現在の式は左ではありません.&は左の値の前に置かなければなりません.左の値だけが参照が有効であることを保証するためです.ほほほ.
C++では、&は引用を表すこともできますが、これはあまり言いません. #include "iostream"
using namespace std;
int main(void)
{ int a = 0;
int &r = a;
cout <"The value is: " <
return 0;
}
ビット単位で「AND」を演算できるほか、変数アドレスを取得する機能も一般的です.
まず、次の簡単な例を見てみましょう.
{
}
上のコードでは、ポインタpは変数aのアドレスを指す.C/C++では、各変数に対応するアドレスがあり、変数識別子の前に&記号を付けることで変数のアドレスを得ることができます.
では、このように書いてもいいですか.int *p = &0x01000;
これは明らかにだめだ.数値定数にはアドレスがないからです.変数にアドレスがあるのは、変数を識別するメモリセルがあるからです(もちろん、変数はレジスタに直接マッピングすることもできます).
次のコードを見てみましょう.
{
int *p = &*(int*)0x0012ff60;
return 0;
上のコードはどうなっていますか?
変数aのアドレスである0 x 0012 ff 60は、以前に調査されているが、ここでのポインタpも実際には変数aのアドレスを指している.
まず、0 x 001 2 ff 60をint*とし、この場合&aと等価である.
そして*(int*)0 x 0012 ff 60は、変数aをとる内容を表す.
最後に、&*(int*)0 x 012 ff 60は、再脱*(int*)0 x 012 ff 60の解参照を表し、また(int*)&aになることに相当する.
したがって,ここでの&は最初の例の&とは異なる意味である.ここの&はアドレスを取るのではなく、1つの*(int*)0 x 001 2 ff 60は変数ではなく、アドレスがありません.各変数識別子は、コンパイル中にコンパイラによってシンボルテーブルを作成し、タイプ、アドレスIDなど、変数識別子に対応するさまざまな属性が格納されます.アドレスIDは、接続後に論理アドレス値を決定します.簡単に言えば、&はアドレス取得動作として動作し、&の後に変数または関数識別子が続く場合にのみ動作する.だからここの&は引用を解くことを表します.
これにより,&アドレス取得操作としての動作結果はコンパイル時に決定される;一方、*は、参照解除操作(またはコンテンツの取得)操作であり、その動作結果は実行時にのみ決定されます.
次の例を見て、印象を深めます.
int main(void)
int a = 0;
int *p = &*&*&a;
printf("The value is: %d/n", *p);
return 0;
ただし、&シンボルは解参照*のように複数回使用できません.変数識別子または1回の解参照の前にしか配置できません.次に例を挙げる
int main(void)
{
int a = 100;
int *p = &a;
int **pp = &p;
int **qq = &*&*pp; // OK
int **rr = *&*&pp; // OK
int **ss = &&**pp; // ERROR
}
1回&を介して参照を解除すると、現在の式は左ではありません.&は左の値の前に置かなければなりません.左の値だけが参照が有効であることを保証するためです.ほほほ.
C++では、&は引用を表すこともできますが、これはあまり言いません.
using namespace std;
{
}