C ポインタ 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(ページの作成:「== ポインタ == プログラムを組み上では、各種の型の変数を使いますが、変数自身はコンピュータ上のメモリ空間に保存されま...」)
 
9行: 9行:
 
更にその3cm~4cmの敷地を同じ樹脂の中に複数枚重ねたり、その樹脂の塊を電子回路基盤に1個~16個くらい<br />
 
更にその3cm~4cmの敷地を同じ樹脂の中に複数枚重ねたり、その樹脂の塊を電子回路基盤に1個~16個くらい<br />
 
とりつけていたり、その電子回路基板を複数個とりつけたりして、現在のNotePCとかでは8GByte(8bitで1Byte(バイト))という容量のものを取り付けて販売している状況です。<br />
 
とりつけていたり、その電子回路基板を複数個とりつけたりして、現在のNotePCとかでは8GByte(8bitで1Byte(バイト))という容量のものを取り付けて販売している状況です。<br />
 +
ある人はプログラム的には一本に並んだ数十億の箱だと言ったりしますが、物理的には、DRAMメモリのある敷地の中のある一点だったり、HDD上においやられた領域だったりするわけです。<br />
 
<br />
 
<br />
 
※単位についてですが、K(キロ)は普通10の3乗で1000ですが、厳密にはコンピュータでは2の10乗の1024Byteが1KByteになります。<br />
 
※単位についてですが、K(キロ)は普通10の3乗で1000ですが、厳密にはコンピュータでは2の10乗の1024Byteが1KByteになります。<br />
25行: 26行:
 
という簡単な基礎知識を頭の片隅に本題に入ります。<br />
 
という簡単な基礎知識を頭の片隅に本題に入ります。<br />
 
例えば<br />
 
例えば<br />
Visual Studio2013では<br />
+
Visual Studio2012では<br />
 
int型は4Byteの変数で使える値の種類は2の4*8bit=32bitで2の32乗=42億9496万7296となります。<br />
 
int型は4Byteの変数で使える値の種類は2の4*8bit=32bitで2の32乗=42億9496万7296となります。<br />
 
実際には負の数も表現できますので、先頭1ビットは正負の記号を表し、0なら正、1なら負数で全部32bit全部が1のときが-1です。2進数の補数ってのを勉強しないとダメかも<br />
 
実際には負の数も表現できますので、先頭1ビットは正負の記号を表し、0なら正、1なら負数で全部32bit全部が1のときが-1です。2進数の補数ってのを勉強しないとダメかも<br />
負数の最大は100000…0000001で、-21億4748万3646~21億4748万3647が表現できる値です。
+
負数の最大は100000…0000001で、-21億4748万3646~21億4748万3647が表現できる値です。<br />
その4Byteを収めてるアドレスは64Bitアドレスなら1844京…の中のどこかから4Byte分のアドレスを使ってるということです。それを覚えさせるのが、ポインタ変数です。
+
その4Byteを収めてるアドレスは64Bitアドレスなら1844京…の中のどこかから4Byte分のアドレスを使ってるということです。それを覚えさせるのが、ポインタ変数です。<br />
 +
<br />
 +
ポインタ変数は<br />
 +
型名 *変数名;<br />
 +
で定義(Definition)できます。<br />
 +
例1:定義<br />
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
int main() {
 +
    int *pintNum;
 +
    int intNum;
 +
}
 +
</syntaxhighlight>
 +
<br />
 +
ポインタのややこしいところは、ポインタ変数を使って代入するときも同じく*を使う事にあるのかもしれません。定義と混同しやすいです。<br />
 +
例2:ポインタ変数での代入<br />
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
int main() {
 +
    int *pintNum;
 +
    int intNum;
 +
    *pintNum = 10; //*を使ってポインタ変数が保持しているアドレスの中身に10を代入。ポインタつまりはアドレスを10にしてる訳ではない。
 +
    std::cout << "intNum="<< intNum << "\n";
 +
    std::cout << "*pintNum="<< *pintNum << "\n";
 +
}
 +
</syntaxhighlight>
 +
実行結果※サンプルの動かし方は[[Cpp クラス]]の一番下に記述があります。
 +
<syntaxhighlight lang="cpp">
 +
intNum=10
 +
*pintNum=10
 +
</syntaxhighlight>
 +
 
 +
pintNumはint型のアドレスを保持した変数。
 +
 
 +
で、アドレスを使っての変数同士のやりとりは
 +
例3:ポインタ変数で実際にアドレスを使う手法<br />
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
int main() {
 +
    int *pintNum;
 +
    int intNum;
 +
    intNum = 50;
 +
    pintNum = &intNum; //これでpintNumはintNumのアドレス番号を記憶。&intNumで変数のアドレスを返す。
 +
    std::cout << "intNum="<< intNum << "\n";
 +
    std::cout << "*pintNum="<< *pintNum << "\n";
 +
    std::cout << "pintNum="<< pintNum << "\n";
 +
    std::cout << "sizeof pintNum="<< sizeof(pintNum) << "\n";
 +
}
 +
実行結果
 +
<syntaxhighlight lang="cpp">
 +
intNum=50
 +
*pintNum=50
 +
pintNum=00000000001BFC34  //ここの結果はプログラム書き方を変えたり、環境が違うと異なる数字になります。
 +
sizeof pintNum=8
 +
</syntaxhighlight>
 +
 
 +
上記のように変数名の前に&をつけるとアドレスを返してくれる。このときの&をアドレス演算子と呼んでいます。<br />
 +
したがってもともとアドレス変数であるpintに対しても&アドレス演算子をつけることができ、アドレス番号を格納しているアドレスが帰ります。
 +
プログラム上ではポインタ変数はint型の変数と同じアドレスを見ることで、名前は違っても同じものを指し示すことができるというのが上記の例です。<br />
 +
pintNumのアドレスはポインタ変数のアドレスで&pintNumですが、更に*をつけると*&pintNumとできこれはpintNumと同じになります。<br />
 +
sizeof関数は、引数に指定した型や値の大きさ、つまりアドレスをいくつ使っているかをbyte単位で返却してくれる関数です。<br />
 +
sizeof(pintNum)とすると32bitアプリケーションのプロジェクトならアドレスの大きさは4Byteなので4が返ってくるし、<br />
 +
64bitアプリケーションのプロジェクトならアドレスの大きさは8Byteですから8が返ってきます。<br />
 +
64bitPCでもプロジェクト設定がWin32なら4が返ってきます。<br />
 +
64bitPCを使っているPCでVisualStudio2012をお使いの場合には、できると思いますが、プロジェクトの設定を変更するには<br />
 +
Visual Studio2012のメニューのプロジェクト(P)->「プロジェクト名(ココも名前の付け方で違うと思います)」のプロパティ(P)<br />
 +
で表示されるダイアログの右上隅にある 構成マネージャー(O)...を押下して表示されるダイアログで<br />
 +
プロジェクトのコンテキスト(ビルドまたは配置するプロジェクト構成をチェック)(R)から<br />
 +
アクティブソリューションプラットフォーム(P)のリストから<nowiki><新規作成...></nowiki>を選択して表示されるダイアログで<br />
 +
新しいプラットフォーム(P)からx64を選択して、あとは変更しないでOKボタンを押下すると新しいプラットフォーム設定にx64が追加され、アクティブになるので<br />
 +
これでx64環境向けのプロジェクトにできます。<br />
 +
独り言になりますが、プラットフォームにARMも選択できるんすね。<br />
 +
 
 +
アドレス覚えるだけだから、ポインタの宣言で型名なんているの?って思った人はC言語初心者の中でも少し洞察力高いと思う。残念ながら型名はいります。<br />
 +
その指し示しているアドレスからどこまでを変数として使っているかを把握する必要があるからです。<br />
 +
さらには、変数が配列になっている場合には、インクリメント演算子で次の配列番号に移動できたりもします。<br />
 +
まぁ少しづつ応用していきましょう。
  
ポインタ変数は
+
ここではポインタとは何かを理解できればよいと思います。
型名 *変数名;
+
文字列は配列ありきなので、ポインタの扱いがさらに複雑化してきますし、構造体やクラスのポインタも複雑な操作が必要になります。
で定義(Definition)できます。
+
int *pintNum;
+
int intNum;
+
intNum = 10;
+
pintNum = &intNum;
+

2013年11月11日 (月) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス