2011-10-06 6 views
1

これは正当なものですか?参照型変数の初期化と格納

int& foo = 0x00000000; 

「int」が正しいデータ型であるかどうかわかりません。アドレスを格納する場合は、どのデータ型を使用しますか?またはポインタを使用する必要がありますか?

これに加えて、これは法的ですか?

int foo = 5; 
int bar = &foo; 

私が求めているのは、ポインタを使用せずにアドレスを格納する方法はありますか?

+1

あなたがしたいと思う理由それ? – delnan

+0

私は確信していません、私はそれについてあまり考えすぎていると思うし、私は本当に内部の仕組みを理解したいです。 – SirYakalot

+0

@SirYakalot:C++標準では、参照がNULLになった場合、コンパイラ/コンピュータがそれを感じるようなことをする可能性があります。通常、クラッシュが発生します。 –

答えて

2

アドレスを保存する場合は、どのデータ型を使用しますか?またはポインタを使用する必要がありますか?

通常は、ポインタを使用します。誰かが一体型にポインタを格納する理由があれば、整数型はポインタ(64ビットポインタなどの場合は64ビット整数)を保持するのに十分な大きさであれば可能です。

C++ 03 AFAIKは依然としてポインタを保持するのに十分な大きさの整数型を持っていませんが、C99はこの目的のためだけのサーバtypedef intptr_tを導入しました。 C++ 11もそれを持っています(std::intptr_tのヘッダ<cstdint>)。

int x; 
intptr_t i=(intptr_t)&x; 

またはより良い

intptr_t i=reinterpret_cast<intptr_t>(&x); 

iの値が定義され、実装されることに注意してください:

あなたはこのようにそれを使用しています。

+0

'reinterpret_cast'は間違いなく必要ありません。アドレスを整数型に変換して戻すことができます。 'uintptr_t'はCの元のポインタと等しいと保証されています) – rubenvb

+0

@rubenvb:ポインタと整数**は互いに暗黙的に*変換できません。確かにC++ではなく(C++標準の段落4.10参照)、C99ではなく(C99標準の6.5.16.1参照)。この場合、他のキャストはしないので、 'reinterpret_cast'が必要です。 – jpalecek

+0

@rubenvbアドレスは、保持するのに十分な大きさの整数型に変換できますが、明示的には変換できません。 'reinterpret_cast'、または' reinterpret_cast'に解決する他の型のキャストが必要です。 –

0

第2のスニペット は完全に細かい がコンパイルされるかもしれませんが、おそらくあなたが望むことはしません。最初は無意味です。

ポインタをintに宣言する場合は、int *fooになります。

ます。次に行うことができます彼らと

int foo = 5; 
int *bar = &foo; 

が、これはあなたができることとできないことで、thusly宣言:

*bar = 6; // foo is now 6. 
bar = 6; // bar now points to the blackness of space 
*bar = 6; // Seg fault! 
+2

私は気晴らしのC++コンパイラが2番目のスニペットを受け入れるとは思わない( 'int *'から 'int'に暗黙的にキャストすることはできない)。 – kennytm

+0

それは間違いなく警告を投げますが、私はそれがまさにそのように起こるのを見ました。 – Chriszuma

+0

さて、gccではデフォルトではエラーです。 '-fpermissive'フラグを渡すことで警告を出すことができます。 – kennytm

1

は、この法律上のですか? int & foo = 0x00000000;

これは合法ですか? int foo = 5; INTバー=キャストが必要とされる整数へのポインタを変換するために&foo;

番号:reinterpret_cast<int>(&foo)。代わりにint* bar = &foo;が必要になるでしょう。

ポインタを使用せずにアドレスを格納する手段はありますか?

いいえ、ポインタはアドレスの格納に使用される要素です。あなたは整数を十分長い整数にキャストすることができます。そして、数字として偽装されたアドレスを '保存'することができます。

参考文献はアドレスではなく、実際には参照は何もありません。それらは既存のオブジェクトの新しい名前に過ぎません。

+0

ポインタ(アドレス)を明示的にキャストしないで 'int'に代入することはできません。 **これを行う**暗黙の変換はありません。 –

+0

@James Kanze:ありがとう、修正済み。 –

0

int& foo = 0x00000000;はリテラルへの参照を試みていますが、リテラルは定数なので動作しません。しかしこれは動作します:

const int& foo = 0x00000000; 

これはあなたのコードでfooを使用しようとするたびに、多くの場合、コンパイラによってポインタとして実装されている0

参考になる整数定数0への参照を作成し、これはあなたには見えない実装の詳細です。

ポインタはアドレスを格納するために作成されたもので、スマートポインタクラスを代わりに使用するのが唯一の理由です。

0

最初のスニペット、

int& foo = 0x00000000; 

は違法です。 がconstへの参照でない限り、一時的に参照を初期化することはできません。以下は合法的です:

int const& foo = 0x00000000; 

しかし、私は誰もそれをやりたい理由を考えることはできません。

extern int const foo = 0x00000000; 

二スニペット、

int foo = 5; 
int bar = &foo; 

も違法である:と 効果的に同じものです。 &fooのタイプはint*であり、暗黙の int*からintの変換はありません。明示的な変換 (reinterpret_cast)を使用することができますが、intがすべて のポインタ値を損失なく保持できるだけの大きさである場合にのみ使用できます。そのような場合は、 intptr_t<stdint.h>)を使用することをお勧めします。これはtypedefであり、すべてのポインタ値を保持するのに十分な整数型 です。 (公式には:<stdint.h>はC90/C++ 11で導入された であり、intptr_tは、十分な積分型がない場合に が存在することが保証されていません。C90/C++ 11はlong longを必要とします。 64ビットであることを、あなたが以上のアドレス空間を持つマシンを持っている場合にのみ 問題になります。私が心配したいものではありませんどの。)

+0

間違っています。標準には 'ptrint_t'はありません。また、少なくとも64ビットであることは「長いlong」を必要としない(しかし、少なくとも64ビット幅の何らかの型を提供する実装を必要とする)。 – jpalecek

+0

@jpalecekかなり明白なタイプミス。これは 'intptr_t'でなければなりません。また、間接的ではあるが、標準では少なくとも64ビットであることが「長い間は長い」必要があります。 ' 'の定義はCと同じでなければならず、Cは' LLONG_MAX'が少なくとも2^63-1であることを要求します。 –