突然想起, 以前学C的时候说, int a=10, 是指一个存储单元中值为10,a为此存储单元的地址,
可是在C#中呢 ?! int a=10, int为一个类, a为一个类实例,a也是一个地址么!?
a中有很多方法, 方法名也是地址么!?
这些名称 在经过编译器编译之后, 都会变成存储器地址!? 名称的长度对程序的性能有影响么 !?
object a =new object(); a为实例的名称。 可是对于类名(Object) ,它算什么? 编译后也会变成地址!?
假设有一个1KB的内存,按字节编址就是0~1024(十进制),第一个字节对应1,第二个字节对应2, ...;程序访问第一个字节也是通过地址1找到存储单元的, 可是1也是个数据啊, 它怎么知道1就是那个存储单元, 这个1又在哪存着呢!? 它又是怎么来的?!
可能我的问题 是因为建立在一个错误的认知上而产生的这些问题!? 还请各位高手各位大哥们指点..感谢。
------解决方案--------------------
你想问除了本身的数据之外 一个类的方法等等是怎么存放的吧?
每个引用类型对象在.net托管堆里面都有一个类型对象 也就是Type类 然后每个实例都有指向Type这个Type类的一个指针 Type类里面存放的是该类的元数据 也就是你说的方法等 然后初次调用方法的时候CLR会去这个TYPE类里面找对应方法的IL代码并将它编译为本地代码 同时修改元数据中方法地址到本地代码的内存地址 再次调用就会去这个地址找方法的本地代码了
------解决方案--------------------
我看过的是这样的
CPU的寄存器分 我是这样分的
数据寄存器(寄存器指到的内存位置会被当成数据读取)
代码(方法)寄存器(寄存器指到的内存位置会被当成方法调用)
比如内存10000这个位置
如果是数据寄存器指向10000 那么他就从这个位置开始读
读多长呢,根据数据类型来
byte读取8bit 也就是将10000到10008这个读到寄存器中
int会读取32bit 10000到10032 读取到寄存器 然后转成数字 当然还可以转换成字母 其他
反正内存中只是一堆1和0
数据寄存器可以读写10000这个位置
代码(方法)寄存器也可以读写10000这个位置
堆栈寄存器也可以读写10000这个位置
可是对于类名(Object) ,它算什么?
类型的作用是决定读取多少个byte(1byte=8bit) cpu通常是以为byte来读写的 不是bit
也就是说cpu的寄存器每次最少读写1byte
C#中有个方法列表的概念 它保证了强类型
方法的定义决定了2个东西
1.从哪里开始的0和1被当成方法
2.需要把多少个参数压入堆栈
再回答 它怎么知道1就是那个存储单元
其实在底层的编程中
数据寄存器可以读写10000这个位置
代码(方法)寄存器也可以读写10000这个位置
堆栈寄存器也可以读写10000这个位置
这个地方是非常有问题 任何寄存器可以读写10000这个位置
这样很容易让程序出错
另外 你可以想象一下
程序A 指向10000 写入8
程序B 指向10000 写入9
程序A 读取10000 读到的9了 它本来是想8+10 现在的结果是19了
很严重把
所以微软提成了进程这个概念
程序A 指向10000 写如8 其实由系统再分配真实内存位置 如20000
程序B 指向10000 写入9 其实由系统再分配真实内存位置 如30000
这样读写的时候就不会出问题了
同理 关于内存中数据是怎么读取的 已经有编译器或系统帮我们完成
怎么知道
当然还是告诉
寄存器从那个地方开始读写 读写多少byte(长度)
------解决方案--------------------
这就是托管程序的概念,最起码地区别,它的地址概念跟c的所谓地址概念是不同的。
------解决方案--------------------
个人建议看两本书
深入理解计算机系统 这边书了解机器级别程序如何运行
CLR VIA C# 这边书了解.net程序如何运行在CLR上面