ポインターと安全でないコード

# 安全でないコードの紹介

C# では、unsafe でマークされている場合、コード ブロックの関数でポインター変数を使用できます。 修飾子。アンセーフ コードまたはアンマネージ コードは、ポインター変数を使用するコード ブロックです。

ポインタは、値が別の変数のアドレス、つまりメモリ位置の直接アドレスである変数です。変数や定数と同様に、変数アドレスを格納するために使用する前に、ポインターを宣言する必要があります。

ポインター宣言の一般的な形式は次のとおりです。

type *var-name;

以下は有効なポインタ宣言です:

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

次の例は、unsafe 修飾子を使用して、C# でポインターを使用する方法を示しています。

using System;
namespace UnsafeCodeApplication
{
   class Program
   {
      static unsafe void Main(string[] args)
      {
         int var = 20;
         int* p = &var;
         Console.WriteLine("Data is: {0} ",  var);
         Console.WriteLine("Address is: {0}",  (int)p);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます:

Data is: 20
Address is: 99215364

メソッド全体を安全でないと宣言する代わりに、コードの一部を安全でないと宣言することもできます:

// safe code
unsafe
{
    // you can use pointers here
}
// safe code

# ポインターを使用して配列要素にアクセスする

C# では、配列名と配列データと同じデータ型へのポインターは、同じ変数型ではありません。例:int *pint[] p 、同じタイプではありません。ポインター変数 p をインクリメントできます メモリ内で固定されていませんが、配列アドレスはメモリ内で固定されており、それをインクリメントすることはできません.

したがって、ポインタ変数を使用して配列データにアクセスする必要がある場合は、C または C++ で伝統的に行っているように、fixed キーワードを使用してポインタを修正する必要があります。

次の例はこれを示しています:

using System;
namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe static void Main()
      {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)
         
         /* let us have array address in pointer */
         for ( int i = 0; i < 3; i++)
         {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }
         
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます:

Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200

# 安全でないコードのコンパイル

安全でないコードをコンパイルするには、 /unsafe を指定する必要があります コマンドライン コンパイラによるコマンドライン スイッチ。

たとえば、安全でないコードを含む prog1.cs という名前のプログラムをコンパイルするには、コマンド ラインから次のコマンドを実行します。

csc /unsafe prog1.cs

Visual Studio IDE を使用している場合は、プロジェクト プロパティでアンセーフ コードの使用を有効にする必要があります。

これを行うには:

  • ソリューション エクスプローラーでプロパティ ノードをダブルクリックして、プロジェクトのプロパティを開きます。
  • - [ビルド] タブをクリックします。
  • 「安全でないコードを許可する」オプションを選択します
  • # ポインターを使用したデータ値の取得

    ToString() メソッドを使用して、ポインタ変数によって参照される場所に格納されているデータを取得できます。次の例はこれを示しています:

    using System;
    namespace UnsafeCodeApplication
    {
       class Program
       {
          public static void Main()
          {
             unsafe
             {
                int var = 20;
                int* p = &var;
                Console.WriteLine("Data is: {0} " , var);
                Console.WriteLine("Data is: {0} " , p->ToString());
                Console.WriteLine("Address is: {0} " , (int)p);
             }
             
             Console.ReadKey();
          }
       }
    }
    
    

    上記のコードをコンパイルして実行すると、次の結果が生成されます:

    Data is: 20
    Data is: 20
    Address is: 77128984
    
    

    # ポインターをパラメーターとしてメソッドに渡す

    ポインター変数をパラメーターとしてメソッドに渡すことができます。次の例はこれを示しています:

    using System;
    namespace UnsafeCodeApplication
    {
       class TestPointer
       {
          public unsafe void swap(int* p, int *q)
          {
             int temp = *p;
             *p = *q;
             *q = temp;
          }
          
          public unsafe static void Main()
          {
             TestPointer p = new TestPointer();
             int var1 = 10;
             int var2 = 20;
             int* x = &var1;
             int* y = &var2;
             
             Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
             p.swap(x, y);
    
             Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
             Console.ReadKey();
          }
       }
    }
    
    

    上記のコードをコンパイルして実行すると、次の結果が生成されます:

    Before Swap: var1: 10, var2: 20
    After Swap: var1: 20, var2: 10
    
    

    No