間接参照(かんせつさんしょう、: indirectionもしくは: indirection reference)とは、コンピュータプログラミング、特にプログラミング言語において、ある (value) を、値そのものによってではなく、名前 (name) や参照 (reference) などにより間接的に指し示すこと、およびその参照自身のことや、それを参照して操作することである。

英語の direct は「指示する」「直接の」という意味があり、indirect は「間接的な」という意味がある。また、indirection は「遠回り」「回り道」という意味がある。通例「参照」という日本語は英語の reference に対応するが、プログラミングの用語および規格の文脈では indirection の一語だけでも「間接参照」を意味する。また、デリファレンス(dereference)とは、参照元から参照先の値を得ることを特に指す語で、「参照外し」とも呼ばれるが、デリファレンスのことを間接参照ということもある。C言語の規格 ISO/IEC 9899[1] および JIS X3010[2] では、後述する間接演算子*によるデリファレンスのことをそれぞれ indirection および間接参照と呼んでいる[3]C++の規格 ISO/IEC 14882[4] および JIS X3014[5] や、C#の規格 ECMA-334、ISO/IEC 23270 および JIS X3015 においても同様である。dereference は、しばしば「逆参照」[6][7][8][9][10][11][12]とも訳されている。

概要

編集

以下、C言語を例に説明する。なお、標準規格では「〜へのポインタ」等として、「アドレス」と直接的に表現するのを避けていることがあるが、ここでは一般的な解釈すなわちポインタはアドレスとする。

C言語では、単項&演算子すなわちアドレス演算子 (address-of operator) を、変数名や関数名など左辺値(代入できるとは限らない)を与えるに作用させると、その式が表すものを指すアドレスを得られる。このアドレスは、対応するポインタ型の変数に、その値として代入したりできる。

単項*演算子すなわち間接演算子[13] (indirection operator) は、デリファレンスを行う演算子である。前述のアドレスを表す式の前に間接演算子を付けると、それを解決(間接参照)して、その指しているもの(の左辺値)を得られる。

間接参照は、実装上のテクニックにとどまるものではなく、たとえばデビッド・ホイーラーによる格言 "All problems in computer science can be solved by another level of indirection." が示すように、問題の解決のためにしばしば必要なものである。

実際の例

編集
  • 宣言
int *p; /* 「int型へのポインタ型」の変数 p を定義。 */
int x; /* int型の変数 x を定義。 */
  • 間接参照
/* ポインタ型の変数 p によって、変数 x を間接参照している。 */
p = &x;
*p = 10;
/* 結果として、x == 10 となる。 */

多重間接参照

編集

C言語では、ポインタ型の変数などに対しても同様に、それを指すポインタを定義することができる。これを多重間接参照 (multiple indirection) と呼ぶ。ポインタへのポインタは二重間接参照 (double indirection) と呼ばれ、俗にダブルポインタとも言う。たとえば構造体Tや文字列char[]配列ソートするとき、構造体や文字列のコピーにかかるコストを避けるため、構造体や文字列の配列を直接操作するのではなく、かわりに構造体を指すポインタの配列や、文字列先頭要素を指すポインタの配列をソートする、ということを行なうことがある。このソート操作の際に、ポインタを指すポインタを使う。このような強力なポインタの機能がC言語の強みであると同時に、エスケープ解析などの静的コード解析を難しくしてもいる。

Pascalでも同様に可能であり、初期のMacintoshのAPIにおいて、メモリ管理をしやすくするために、「ハンドル」と呼ぶ、ポインタへのポインタを使用していた(参考: en:Mac OS memory management#Fragmentation)。

さらに、「ポインタのポインタのポインタ」「ポインタのポインタのポインタのポインタ」など、いくらでも定義することができるが、通常は必要がないため利用されない。

  • ポインタへのポインタの例
int **pp;
int *p;
int x;
p = &x;
pp = &p;
**pp = 10;

脚注・参照

編集
  1. ^ 6.5.3.2 Address and indirection operators
  2. ^ 6.5.3.2 アドレス及び間接演算子
  3. ^ dereference という言葉自体は、C言語の規格ではほとんど使われていない。なお、ISO/IEC 9899における "dereferencing a pointer by the unary * operator" は、JIS X3010で「単項*演算子によるポインタ参照」と翻訳されている。
  4. ^ 5.3.1 Unary operators
  5. ^ 5.3.1 単項演算子
  6. ^ null ポインターの逆参照が引き起こす未定義の動作 | iSUS
  7. ^ System.Pointer - RAD Studio API Documentation(英語)
  8. ^ System.Pointer - RAD Studio API Documentation(日本語)
  9. ^ C++ - From Algorithms to Coroutines in C++ | Microsoft Docs
  10. ^ C++ - C++ でのアルゴリズムからコルーチンまで | Microsoft Docs
  11. ^ Pointer related operators - C# reference | Microsoft Docs
  12. ^ ポインターに関連する演算子 - C# リファレンス | Microsoft Docs
  13. ^ もしくは間接参照演算子とも。

関連項目

編集

外部リンク

編集