C ポインタ 新しいページはコチラ
提供: yonewiki
51行: | 51行: | ||
int *pintNum; | int *pintNum; | ||
int intNum; | int intNum; | ||
+ | pintNum = new int; | ||
*pintNum = 10; //*を使ってポインタ変数が保持しているアドレスの中身に10を代入。ポインタつまりはアドレスを10にしてる訳ではない。 | *pintNum = 10; //*を使ってポインタ変数が保持しているアドレスの中身に10を代入。ポインタつまりはアドレスを10にしてる訳ではない。 | ||
std::cout << "intNum="<< intNum << "\n"; | std::cout << "intNum="<< intNum << "\n"; | ||
− | std::cout << "*pintNum="<< *pintNum << "\n"; | + | std::cout << "*pintNum="<< *pintNum << "\n"; |
+ | delete pintNum; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
62行: | 64行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | pintNumはint型のアドレスを保持するための変数ですが、ポインタ変数の宣言以外の所で*pintnumと*をポインタ変数の前につけるとアドレスが指し示す中身を、<br /> | |
+ | 定義されている型にしたがって代入したり、内容を取り出したりすることができます。<br /> | ||
+ | 但し、最初に宣言された段階ではint型のアドレスを保持できるだけで、アドレスは保持していません。つまり、その実体、内容つまり中身、も*pintNumと指定したとしても、<br /> | ||
+ | 中身への代入はできません。したがって宣言した直後に *pinNum=10; としてもエラーになります。<br /> | ||
+ | その問題を解決するのがnew演算子です。new演算子はポインタ変数の型と同じint型で、ポインタが指し示す先頭アドレスの生成と先頭アドレスからint型の分だけメモリ領域を確保し、<br /> | ||
+ | ポインタ変数にアドレスを格納します。この結果アドレスの中身の方には名前がない状態ではありますが、ポインタ変数からでのみ操作できる変数が生成されたことになります。<br /> | ||
+ | 名もなき実体のアドレスをポインタ変数だけがしっているということです。delete演算子では、そうやって生成した名もなき実体のメモリ領域を解放することになります。<br /> | ||
+ | もうここから先では使いません。どうぞご自由にという感じです。その宣言がされるまではずっとメモリ領域を確保し続けます。最近ではプログラムが終了したときに、このような手法で<br /> | ||
+ | メモリ領域を確保した部分の解放処理をしてくれるようになりましたが、その昔、これを解放せずにプログラムが終わるという事態が多発していたのも事実です。<br /> | ||
+ | 使い終わったらいち早くかたずけることで資源を有効に利用できるのです。プログラム終了時に全部の片づけをやってくれてるのかは知りませんが…そういうことらしいです。<br /> | ||
− | + | <br /> | |
+ | そして、アドレスそのものを使っての変数同士のやりとりは以下の例ように記述します。<br /> | ||
例3:ポインタ変数で実際にアドレスを使う手法<br /> | 例3:ポインタ変数で実際にアドレスを使う手法<br /> | ||
<syntaxhighlight lang="cpp" line start="1"> | <syntaxhighlight lang="cpp" line start="1"> | ||
78行: | 90行: | ||
std::cout << "sizeof pintNum="<< sizeof(pintNum) << "\n"; | std::cout << "sizeof pintNum="<< sizeof(pintNum) << "\n"; | ||
} | } | ||
+ | </syntaxhighlight> | ||
実行結果 | 実行結果 | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
90行: | 103行: | ||
プログラム上ではポインタ変数はint型の変数と同じアドレスを見ることで、名前は違っても同じものを指し示すことができるというのが上記の例です。<br /> | プログラム上ではポインタ変数はint型の変数と同じアドレスを見ることで、名前は違っても同じものを指し示すことができるというのが上記の例です。<br /> | ||
pintNumのアドレスはポインタ変数のアドレスで&pintNumですが、更に*をつけると*&pintNumとできこれはpintNumと同じになります。<br /> | pintNumのアドレスはポインタ変数のアドレスで&pintNumですが、更に*をつけると*&pintNumとできこれはpintNumと同じになります。<br /> | ||
− | + | sizeof関数は、引数に指定した型や値の大きさ、つまりアドレスをいくつ分、使っているのか、使うのかをbyte単位で返却してくれる関数です。<br /> | |
sizeof(pintNum)とすると32bitアプリケーションのプロジェクトならアドレスの大きさは4Byteなので4が返ってくるし、<br /> | sizeof(pintNum)とすると32bitアプリケーションのプロジェクトならアドレスの大きさは4Byteなので4が返ってくるし、<br /> | ||
64bitアプリケーションのプロジェクトならアドレスの大きさは8Byteですから8が返ってきます。<br /> | 64bitアプリケーションのプロジェクトならアドレスの大きさは8Byteですから8が返ってきます。<br /> | ||
103行: | 116行: | ||
独り言になりますが、プラットフォームにARMも選択できるんすね。<br /> | 独り言になりますが、プラットフォームにARMも選択できるんすね。<br /> | ||
− | + | アドレス覚えるだけだから、ポインタの宣言で型名なんているの?って思った人はC言語初心者の中でも少し洞察力が高いと思う。残念ながら型名はいります。<br /> | |
− | + | その指し示しているアドレスからどこまでを変数として使っているかを把握する必要があるからです。代入もできるわけですから<br /> | |
さらには、変数が配列になっている場合には、インクリメント演算子で次の配列番号に移動できたりもします。<br /> | さらには、変数が配列になっている場合には、インクリメント演算子で次の配列番号に移動できたりもします。<br /> | ||
まぁ少しづつ応用していきましょう。 | まぁ少しづつ応用していきましょう。 |