ポインタ (プログラミング)

出典: フリー百科事典『ウィキペディア(Wikipedia)』
Jump to navigation Jump to search

ポインタ (: pointer) とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照する(指し示す)ものである。有名な例としては Pascal のポインタが挙げられる。

なお、C++では、さらに独立した「参照」という機能がある。

Pascalのポインタ[編集]

ポインタの例としては、Pascalによるポインタが挙げられる。

宣言[編集]

Pascal では次のようにして、変数 p がデータ型 T のメモリー領域を指すポインタ用であることを宣言する。

var p : ^T ;

何も指していないことを示す特別な値[編集]

未初期化のポインタ変数は、不定の領域を指している。しかし、その場合、「未初期化状態」と「有効な領域を指している状態」の区別がつかない。そのため、ヌル値 nil を代入することによって、ポインタが無効な領域を指していることを明示する必要がある。

p := nil ;

変数へのポインタ[編集]

Pascal では、演算子 @ を用いると T 型の既存の変数 x へのポインタを取得することができる。

p := @x ;

ポインタ変数 p が指している値を参照するには演算子 ^ を使って次のように記述する。

p^

動的なポインター[編集]

Pascal ではポインター変数には既存の変数へのポインターだけでなく実行時に新しいメモリー領域を取得してそこへのポインターを割り当てることもできる。

new (p) ;

これによって取得されたメモリー領域は、次のようにして開放しなければならない。

dispose (p) ;

利用例[編集]

次の例は線形リストのセルを作成するものである。

type
  IntegerList = ^IntegerCell ;
  IntegerCell = record
    value : integer ;
    next  : IntegerList
  end ;

function new_IntegerList (value:integer ; next:IntegerList) : IntegerList
var
  il : IntegerList ;
begin
  new (il); 
  if il = nil then new_IntegerList := nil ;
  il^.value := value ;
  il^.next := next ;
  new_IntegerList := il
end ;

実行時に取得したメモリー領域は下記のように解放できる。

procedure delete_IntegerList (il:IntegerList)
begin
  dispose (il)
end ;

C言語のポインタ[編集]

ポインタの別の例としては、C言語による「特定のメモリ領域を表現する」ポインタが挙げられる。

C言語にポインタが存在する理由は、効率上の問題である。C言語は、元々UNIXを記述するシステム用言語として開発されたものである。したがって、アセンブラが実行できる操作のほぼ全てを行える必要があった。そのため、一般的な変数へのポインタのほか、関数のエントリーポイントへのポインタを扱うことも出来るし、数値で指定するメモリ領域への値の直接代入能力を持つなど、他のプログラミング言語と比較して、むしろ異例とも言える強力なポインタ機能を備えている。

しかし、コード領域も含むメモリを直接扱えるということは、言語レベルでは(意図的でないとしても)不正なメモリアクセスを事実上保護できないということを示しており、C言語のプログラムにおけるポインタ関連のバグの多さがそれを証明している。

宣言[編集]

C言語では次のようにして、変数 p がデータ型 T のメモリー領域を指すポインタ用であることを宣言する。

T *p ;

何も指していないことを示す特別な値[編集]

未初期化のポインタ変数は、不定の領域を指している。しかし、その場合、「未初期化状態」と「有効な領域を指している状態」の区別がつかない。そのため、ヌル値 NULL を代入することによって、ポインタが無効な領域を指していることを明示する必要がある。

p = NULL ;

変数へのポインタ[編集]

C言語では、演算子 & を用いると T 型の既存の変数 x へのポインタを取得することができる。

p = &x ;

ポインタ変数 p が指している値を参照するには演算子 * を使って次のように記述する。

*p

動的なポインター[編集]

C言語ではポインター変数には既存の変数へのポインターだけでなく実行時に新しいメモリー領域を取得してそこへのポインターを割り当てることもできる。

p = (T*) malloc (sizeof (T)) ;

これによって取得されたメモリー領域は、次のようにして開放しなければならない。

free (p) ;

利用例[編集]

次の例は線形リストのセルを作成するものである。

struct IntList
  {
  int value ;
  struct IntList *next ;
  } ;

struct IntList *new_IntList (int value, struct IntList *next)
  {
  struct IntList *il = (struct IntList *) malloc (sizeof (struct IntList)) ;
  if (il==NULL) return NULL ;
  (*il).value = value ;
  (*il).next = next ;
  return il ;
  }

実行時に取得したメモリー領域は下記のように解放できる。

関数へのポインタ[編集]

上述の通り、C言語では関数を指すポインタを作成することができる。関数ポインタを使うことで処理の一部を実行時に与えられた外部の関数に委託する高階関数を作ることもできる。標準ライブラリ関数ではsortがこの一例である。

宣言[編集]

引数の型がdoubleで、返値の型が double である関数を受け取るポインタ型変数 f を宣言する場合。

double (*f)(double) ;

ポインタが指している関数の呼び出し[編集]

f = sqrt ;
printf("f(16) = %g\n", f(16));
printf("f(25) = %g\n", (*f)(25)); /* 明示のためかこちらの方が使われやすい */

広義のポインタ[編集]

ポインタ概念はたとえば、配列中にオブジェクトを格納し、それを要素のインデックスで参照すれば、これは広義のポインタといえる。またファイルシステムのソフトリンクや、インターネット上の文書を指し示す URL も広義のポインタである。

参考: C++における「参照」[編集]

C++における参照は、既存の変数に別名を付ける仕組みだといえる。

int nipponHousouKyoukai = 1 ;
int& nhk = nipponHousouKyoukai ; // nhk を nipponHousouKyoukai への参照で初期化する

この場合変数 nhknipponHousouKyoukai を参照している。nhknipponHousouKyoukai は実体を共有しているので nhk と呼んでも nipponHousouKyoukai と呼んでも同じものを表す。すなわち変数 nipponHousouKyoukai に別名 nhk が付いたことになる。

脚注[編集]

[ヘルプ]

関連項目[編集]