ポインタを演算する
ポインタに使用できるのは“++”や“--”演算子だけではない。四則演算や“==”などの比較演算子も使用できる。以下はポインタの引き算を、データ型を変えながら実行してみたサンプル・ソースである。
1: using System;
2:
3: namespace ConsoleApplication9
4: {
5: class Class1
6: {
7: unsafe static void test()
8: {
9: int [] array = { 1,2,3,4 };
10: fixed( int * p1 = &array[0] )
11: {
12: fixed( int * p2 = &array[3] )
13: {
14: Console.WriteLine( p2-p1 );
15:
16: short * p3 = (short *)p1;
17: short * p4 = (short *)p2;
18: Console.WriteLine( p4-p3 );
19:
20: sbyte * p5 = (sbyte *)p1;
21: sbyte * p6 = (sbyte *)p2;
22: Console.WriteLine( p6-p5 );
23: }
24: }
25: }
26: static void Main(string[] args)
27: {
28: test();
29: }
30: }
31: }
|
|
ポインタの演算を行っているサンプル・プログラム7 |
配列の先頭と末尾へのポインタ間で、データ型を変えながら引き算を行っている。 |
これを実行すると以下のようになる。
|
サンプル・プログラム7の実行結果 |
ポインタのサイズにより引き算の結果は異なってくる。
|
14行目では、int型のポインタとして引き算をしている。18行目ではまったく同じ値を、データ型だけshortへのポインタに変換したうえで計算している。22行目では同様にsbyte型で行っている。結果は見てのとおりで、ポインタのサイズを意識して、結果が異なっていることが分かるだろう。つまり、p1とp2の間には、int型なら3個分、short型なら6個分、sbyte型なら12個分のすき間があるということが示されているわけである。
一時変数を容易に確保するstackalloc
量の多いデータを扱う場合は配列を利用するのが1つの定石だが、配列は移動型であるため、ポインタ・アクセスが面倒になる。そこで、スタック上に配列のようなサイズの大きなデータを確保できれば扱いやすい。そのために、C#ではstackallocというキーワードが用意されている。これはC言語のalloca関数のようなものといえる。以下はそれを使用した例である。
1: using System;
2:
3: namespace ConsoleApplication11
4: {
5: class Class1
6: {
7: static void Main(string[] args)
8: {
9: unsafe
10: {
11: int * buffer = stackalloc int[4];
12: for( int i=0; i<4; i++ )
13: {
14: *(buffer + i) = i;
15: }
16: for( int i=0; i<4; i++ )
17: {
18: Console.WriteLine( buffer[i] );
19: }
20: }
21: }
22: }
23: } |
|
stackallocキーワードを使用したサンプル・プログラム8 |
通常、配列は移動型であるが、stackallocキーワードを付けることによってスタック上に割り当てることができる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム8の実行結果 |
ポインタにより順番に配列へ値を代入し、それを表示している。
|
このように、配列でありながらfixedステートメントなしで処理できることが分かると思う。なお、ここでは2つ確認しておきたいことがある。第1は14行目である。このようなポインタを用いた式を使って配列にアクセスすることは、もちろん可能である。第2は、9〜20行目のunsafeブロックである。unsafeキーワードはメソッドなどに付けるだけでなく、ブロックを構成する使い方もできる。もし、メソッドの一部だけでunsafeコードを使用する場合は、このようなunsafeブロックを使った方が安全だろう。
なお、stackallocしたメモリは、そのブロックを抜けると解放されてしまう。あくまでローカルな存在であることに注意が必要だ。stackallocしたメモリへの参照を戻り値として返すような使い方はできない。
Insider.NET 記事ランキング
本日
月間