zhcn 编程语言 Golang Go 文件处理 非公開: C# 指针和不安全

C# 指针和不安全

为了维护类型安全,C#默认不支持指针,但是如果使用unsafe关键字来修饰类或者类的成员,这样的类或者类的成员就被认为是不安全的代码,C#允许使用。不安全代码中的指针变量。在公共语言运行时 (CLR) 中,不安全代码是无法验证的代码。不安全的代码不一定是危险的,但 CLR 无法验证代码是否安全。因此,CLR 仅执行受信任程序集中的不安全代码。

指针变量

在C#中,指针也是一个变量,但它的值是另一个变量的内存地址。指针在使用之前也必须声明。声明指针的语法是:

type* var_name;

下表显示了定义指针的一些示例。

例子解释
整数*p p 是一个指向整数的指针
双*p p 是一个指向 double 的指针
浮动*p p 是一个指向浮点数的指针
整数**p p 是一个指向整数的指针
整数*[]p p 是指向整数的一维指针数组。
字符*p是一个指向字符的指针
无效*p p 是一个指向未知类型的指针

与声明变量类似,您也可以在一行代码中声明多个指针:

int* p1, p2, p3;  

注意:指针类型不能从对象继承,装箱和拆箱不支持指针,但不同指针类型之间以及指针和整数之间可以进行转换。

[示例] 下面的示例演示了 C# 中不安全关键字和指针的使用。

 using System;

namespace it-kiso.com
{
    class Demo
    {
        static unsafe void Main(string[] args)
        {
            double f = 3.1415;
            double* p = &f;
            Console.WriteLine("データの内容は: {0} ",  f);
            Console.WriteLine("データのメモリアドレスは: {0}",  (int)p);
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

データの内容は: 3.1415
データのメモリアドレスは: 11530344

提示:编译上述代码时,需要在编译命令中添加-unsafe (例如csc -unsafe demo.cs )。

将指针作为参数传递给函数

您可以将指针变量作为参数传递给函数,如以下示例所示。

 use System;

namespace it-kiso.com
{
    class Demo
    {
        public unsafe void swap(int* p, int *q)
        {
            int temp = *p;
            *p = *q;
            *q = temp;
        }

        public unsafe static void Main()
        {
            Demo p = new Demo();
            int var1 = 10;
            int var2 = 20;
            int* x = &var1;
            int* y = &var2;

            Console.WriteLine("Swap 関数呼び出し前: var1:{0}, var2: {1}", var1, var2);
            p.swap(x, y);

            Console.WriteLine("Swap 関数呼び出し後: var1:{0}, var2: {1}", var1, var2);
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

Swap 関数呼び出し前: var1:10, var2: 20
Swap 関数呼び出し後: var1:20, var2: 10

使用指针访问数组元素

在 C# 中,数组和同名数组的指针是不同类型的数据。例如, int* pint[] p是不同类型的数据。指针变量p的值可以递增,因为它在内存中不固定,但数组p的值不能递增,因为数组地址在内存中是固定的。如果需要使用指针变量来访问数组数据,可以使用fixed关键字来修复指针,就像在C或C++中一样。我们举个例子:

 using System;

namespace it-kiso.com
{
    class Demo
    {
        public unsafe static void Main()
        {
            int[] list = { 10, 100, 200 };
            fixed(int *ptr = list)

            /* ポインター中の配列のアドレスを表示する */
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("list[{0}] のメモリーアドレスは:{1}", i, (int)(ptr + i));
                Console.WriteLine("list[{0}] の値は:{1}", i, *(ptr + i));
            }
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

list[0] のメモリーアドレスは: 51981272
list[0] の値は: 10
list[1] のメモリーアドレスは: 51981276
list[1] の値は: 100
list[2] のメモリーアドレスは: 51981280
list[2] の値は: 200

编译不安全代码

要编译不安全的代码,编译时必须使用unsafe命令。例如,编译包含不安全代码的demo.cs程序的命令是:

csc /unsafe demo.cs

csc -unsafe demo.cs

如果您使用的是 Visual Studio,则必须在项目属性中启用不安全代码。以下是具体步骤:

  • 通过双击解决方案资源管理器中的属性节点来打开项目属性。
  • 单击“构建”选项卡。
  • 选择“允许不安全代码”选项。

通俗易懂的讲解《C#指针变量和不安全性》!您必须观看的 2 个最佳视频

【新しいC言語講座】ポインタの基本(1)
https://www.youtube.com/watch?v=KgzfjriHNOc&pp=ygUxIEMjIOODneOCpOODs-OCv-ODvOWkieaVsOOBqOWuieWFqOOBp-OBquOBhCZobD1KQQ%3D%3D
【C言語】ポインタがわかりません。教えてください。【プログラミング】
https://www.youtube.com/watch?v=Kh45nqpgPoc&pp=ygUxIEMjIOODneOCpOODs-OCv-ODvOWkieaVsOOBqOWuieWFqOOBp-OBquOBhCZobD1KQQ%3D%3D
为了维护类型安全,C#默认不支持指针,但是如果使用unsafe关键字来修饰类或者类的成员,这样的类或者类的成员就被认为是不安全的代码,C#允许使用。不安全代码中的指针变量。在公共语言运行时 (CLR) 中,不安全代码是无法验证的代码。不安全的代码不一定是危险的,但 CLR 无法验证代码是否安全。因此,CLR 仅执行受信任程序集中的不安全代码。

指针变量

在C#中,指针也是一个变量,但它的值是另一个变量的内存地址。指针在使用之前也必须声明。声明指针的语法是:

type* var_name;

下表显示了定义指针的一些示例。

例子解释
整数*p p 是一个指向整数的指针
双*p p 是一个指向 double 的指针
浮动*p p 是一个指向浮点数的指针
整数**p p 是一个指向整数的指针
整数*[]p p 是指向整数的一维指针数组。
字符*p是一个指向字符的指针
无效*p p 是一个指向未知类型的指针

与声明变量类似,您也可以在一行代码中声明多个指针:

int* p1, p2, p3;  

注意:指针类型不能从对象继承,装箱和拆箱不支持指针,但不同指针类型之间以及指针和整数之间可以进行转换。

[示例] 下面的示例演示了 C# 中不安全关键字和指针的使用。

 using System;

namespace it-kiso.com
{
    class Demo
    {
        static unsafe void Main(string[] args)
        {
            double f = 3.1415;
            double* p = &f;
            Console.WriteLine("データの内容は: {0} ",  f);
            Console.WriteLine("データのメモリアドレスは: {0}",  (int)p);
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

データの内容は: 3.1415
データのメモリアドレスは: 11530344

提示:编译上述代码时,需要在编译命令中添加-unsafe (例如csc -unsafe demo.cs )。

将指针作为参数传递给函数

您可以将指针变量作为参数传递给函数,如以下示例所示。

 use System;

namespace it-kiso.com
{
    class Demo
    {
        public unsafe void swap(int* p, int *q)
        {
            int temp = *p;
            *p = *q;
            *q = temp;
        }

        public unsafe static void Main()
        {
            Demo p = new Demo();
            int var1 = 10;
            int var2 = 20;
            int* x = &var1;
            int* y = &var2;

            Console.WriteLine("Swap 関数呼び出し前: var1:{0}, var2: {1}", var1, var2);
            p.swap(x, y);

            Console.WriteLine("Swap 関数呼び出し後: var1:{0}, var2: {1}", var1, var2);
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

Swap 関数呼び出し前: var1:10, var2: 20
Swap 関数呼び出し後: var1:20, var2: 10

使用指针访问数组元素

在 C# 中,数组和同名数组的指针是不同类型的数据。例如, int* pint[] p是不同类型的数据。指针变量p的值可以递增,因为它在内存中不固定,但数组p的值不能递增,因为数组地址在内存中是固定的。如果需要使用指针变量来访问数组数据,可以使用fixed关键字来修复指针,就像在C或C++中一样。我们举个例子:

 using System;

namespace it-kiso.com
{
    class Demo
    {
        public unsafe static void Main()
        {
            int[] list = { 10, 100, 200 };
            fixed(int *ptr = list)

            /* ポインター中の配列のアドレスを表示する */
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("list[{0}] のメモリーアドレスは:{1}", i, (int)(ptr + i));
                Console.WriteLine("list[{0}] の値は:{1}", i, *(ptr + i));
            }
            Console.ReadKey();
        }
    }
} 

操作的结果将是:

list[0] のメモリーアドレスは: 51981272
list[0] の値は: 10
list[1] のメモリーアドレスは: 51981276
list[1] の値は: 100
list[2] のメモリーアドレスは: 51981280
list[2] の値は: 200

编译不安全代码

要编译不安全的代码,编译时必须使用unsafe命令。例如,编译包含不安全代码的demo.cs程序的命令是:

csc /unsafe demo.cs

csc -unsafe demo.cs

如果您使用的是 Visual Studio,则必须在项目属性中启用不安全代码。以下是具体步骤:

  • 通过双击解决方案资源管理器中的属性节点来打开项目属性。
  • 单击“构建”选项卡。
  • 选择“允许不安全代码”选项。

通俗易懂的讲解《C#指针变量和不安全性》!您必须观看的 2 个最佳视频

【新しいC言語講座】ポインタの基本(1)
https://www.youtube.com/watch?v=KgzfjriHNOc&pp=ygUxIEMjIOODneOCpOODs-OCv-ODvOWkieaVsOOBqOWuieWFqOOBp-OBquOBhCZobD1KQQ%3D%3D
【C言語】ポインタがわかりません。教えてください。【プログラミング】
https://www.youtube.com/watch?v=Kh45nqpgPoc&pp=ygUxIEMjIOODneOCpOODs-OCv-ODvOWkieaVsOOBqOWuieWFqOOBp-OBquOBhCZobD1KQQ%3D%3D