Учебники

C # — Небезопасные коды

C # позволяет использовать переменные-указатели в функции блока кода, когда он отмечен модификатором unsafe . Небезопасный код или неуправляемый код — это блок кода, который использует переменную- указатель .

Примечание. Для выполнения программ, упомянутых в этой главе, на площадке кодирования установите параметр компиляции в « Проект»> «Параметры компиляции»> «Команда компиляции» на

mcs *.cs -out:main.exe -unsafe"

Примечание. Для выполнения программ, упомянутых в этой главе, на площадке кодирования установите параметр компиляции в « Проект»> «Параметры компиляции»> «Команда компиляции» на

mcs *.cs -out:main.exe -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 */

В следующем примере показано использование указателей в C # с использованием модификатора unsafe —

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

Вместо того, чтобы объявлять весь метод небезопасным, вы также можете объявить часть кода небезопасной. Пример в следующем разделе показывает это.

Получение значения данных с помощью указателя

Вы можете извлечь данные, хранящиеся в расположении, на которое ссылается переменная указателя, используя метод 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

Доступ к элементам массива с помощью указателя

В C # имя массива и указатель на тип данных, совпадающий с данными массива, не совпадают с типом переменной. Например, int * p и int [] p не имеют одинаковый тип. Вы можете увеличивать переменную-указатель p, потому что она не фиксирована в памяти, а адрес массива фиксирован в памяти, и вы не можете увеличить его.

Поэтому, если вам нужен доступ к данным массива с помощью переменной указателя, как мы обычно делаем в C или 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, вам нужно разрешить использование небезопасного кода в свойствах проекта.

Для этого —

Откройте свойства проекта , дважды щелкнув узел свойств в обозревателе решений.

Нажмите на вкладку Build .

Выберите опцию « Разрешить небезопасный код ».