• 从内存变化看.NET代码执行机理(四)


     1    class Program
     2    {
     3        public static void text(int x)
     4        {
     5            Console.WriteLine("第5行代码:" + x);
     6            x = x * 2;
     7            Console.WriteLine("第7行代码:" + x);
     8         }

     9        static void Main(string[] args)
    10        {
    11            int a;
    12            a = 5;
    13            Console.WriteLine("第13行代码:" + a);
    14            text(a);
    15            Console.WriteLine("第15行代码:" + a);
    16            Console.ReadKey();
    17        }

    18    }
    以上我们定名叫程序a,首先不要马上把代码拷贝到IDE里面去运行,用自己脑子想想,以上代码运行结果是什么?
    第13行代码:5
    第5行代码:5
    第7行代码:10
    第15行代码:10
    还是
    第13行代码:5
    第5行代码:5
    第7行代码:10
    第15行代码:5
    你认为是哪个?从内存的变化中来分析是为什么?
    好,代码改一下,在上面代码的基础上只加两个ref关键字,程序b
     1    class Program
     2    {
     3        public static void text(ref int x)
     4        {
     5            Console.WriteLine("第5行代码:" + x);
     6            x = x * 2;
     7            Console.WriteLine("第7行代码:" + x);
     8         }

     9        static void Main(string[] args)
    10        {
    11            int a;
    12            a = 5;
    13            Console.WriteLine("第13行代码:" + a);
    14            text(ref a);
    15            Console.WriteLine("第15行代码:" + a);
    16            Console.ReadKey();
    17        }

    18    }

    现在运行结果是什么?注意别动IED,用脑子考虑.
    再改一下,注意中间变化(程序c)
     1    class Program
     2    {
     3        public static void text(out int x)
     4        {   x = 15;
     5            Console.WriteLine("第5行代码:" + x);
     6            x = x * 2;
     7            Console.WriteLine("第7行代码:" + x);
     8         }

     9        static void Main(string[] args)
    10        {
    11            int a;
    12            a = 5;
    13            Console.WriteLine("第13行代码:" + a);
    14            text(out a);
    15            Console.WriteLine("第15行代码:" + a);
    16            Console.ReadKey();
    17        }

    18    }

    现在的运行结果是什么?
    从内存的角度来看,程序a很简单.其运行结果为
    第13行代码:5
    第5行代码:5
    第7行代码:10
    第15行代码:5
    疑点如果有的话,应该是在最后第15行代码的输出上,为什么不是10?因为

    x在得到text(a);后自己在栈中申请了一份内存,并把a的内容5复制了一份到自己的内容中,然后做5*2操作,最后X的值为10,而a的值一直是5不变.

    程序b的运行结果是
    第13行代码:5
    第5行代码:5
    第7行代码:10
    第15行代码:10
    看起来变化的是第15行代码的输出,其实从内存里面看,机理和程序a完全不一样(实参地址考入形参)

    text(ref a)public static void text(ref int x)表示为传址方式,既x在text(ref a)的时候得到的不是5这个数值,而是存放5的内存地址123456.x从地址123456映射到a中的数值5.如果x做乘2操作,那么系统读取x内存的内容时发现是栈地址123456,将会延着这个地址跟踪操作到a中的数值5.乘2后a中的5变10,x中的地址123456不变.
    程序c中的运行结果为
    第13行代码:5
    第5行代码:15
    第7行代码:30
    第15行代码:30
    其运行机理与程序b正好相反.(形参地址考入实参)
    首先申明a在栈中申请一块内存,并赋值5,地址为123456

    执行text(out a)--public static void text(out int x)后, x在内存中申请一块内存,同时把x的内存地址考进a的内容中,x的内存内容为空.

    然后代码给出定义x=15.x的内存内容刷成15.

    后面的计算就简单了,x*2表示从x中15*2=30,表示x最终被刷成30,而a是通过x的内存地址123457指向x的内存内容.所以第7行代码和第15行代码输出都是30.

    可以把x=15拿掉测试一下,加深理解!
  • 相关阅读:
    OpenSSL EVP_Digest系列函数的一个样例
    简单的函数指针使用
    写入简单的日志log
    C实现日志等级控制
    散列表
    数据结构-链表
    关于线程的几个函数
    MySQL什么时候会使用内部临时表?
    linux如何处理多连接请求?
    Centos下搭建nginx反向代理
  • 原文地址:https://www.cnblogs.com/tommyli/p/1349695.html
Copyright © 2020-2023  润新知