2005年12月19日
配列へのポインタと配列へのリファレンス
C/C++ のあまり使われない機能に、配列へのポインタと配列へのリファレンスがあります。ここでは、それらがどのようなものかまとめたいと思います。
配列へのポインタ
C 言語には配列の先頭要素へのポインタとは別に配列へのポインタ が存在します。。プログラミング言語Cの 5.7 に多次元配列を受け取る関数の例が載っています。
次のプログラムではサイズ 256 の char 型の配列を作り、その配列へのポインタ p を作っています。++p を実行すると p の指すアドレスは 256 バイト分進みます。
#include <stdio.h> int main() { char foo[256]; char (*p)[sizeof(foo)] = &foo; printf("%p\n", p); ++p; printf("%p\n", p); // 256 バイト分進む return 0; }
配列へのリファレンス
C++ には配列へのリファレンスがあります。通常、配列のデータを関数に渡すときはポインタと長さで渡したり、末尾に番兵を添えてポインタで渡したりしますが、C++ では配列へのリファレンスを使う方法もあります。
次のプログラムでは "abc" という文字列の配列 foo を作り、その配列へのリファレンス ref を作っています。ref[0] を書き換えると foo の1文字目が書き換わります。
#include <stdio.h> int main() { char foo[] = "abcdef"; char (&ref)[sizeof(foo)] = foo; ref[0] = 'A'; printf("%s\n", foo); // "Abcdef" が表示される printf("%d\n", sizeof(ref)); // これは 7 return 0; }
まとめ
どちらの機能も使う機会はそれほどなさそうですが、覚えておくといざというときに役立つかもしれません。これは万能の言い訳、「覚えておくといざというときに役立つかもしれない、という口実で雑多な知識を吸収してしまう」の法則という気もしますが、いざというときの一例がみつかりました。
この例では、配列へのリファレンスとテンプレートを組み合わせて、文字列へのハッシュ関数の適用をコンパイル時に行っています。コンパイラの最適化により、文字列の長さと同じ数だけ生成されるはずのテンプレート関数はすべて消えて整数値 (この場合 1064) だけが残る仕組みです。覚えておくといざというときに役に立ちそうですね。