听起来很吊的堆与栈其实也不过如此

一、在讲堆栈之前,我们先看看值类型和引用类型:

1,我们看看值类型与引用类型的存储方式:

引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实例。类对象的引用还是存储在栈中。

值类型:值类型总是分配在它声明的地方,做为局部变量时,存储在栈上;类对象的字段时,则跟随此类存储在堆中。

什么是堆什么是栈我们后面解释。

图1-1

2,我们再看看引用类型与值类型的区别:

①引用类型和值类型都继承自Systerm.Object类。不同之处,几乎所有的引用类型都是直接从Systerm.Object继承,而值类型则是继承Systerm.Object的子类Systerm.ValueType类。

②我们在给引用类型的变量赋值的时候,其实只是赋值了对象的引用;而给值类型变量赋值的时候是创建了一个副本(副本不明白?说通俗点,就是克隆了一个变量)。

文字不够形象?我们上代码看看

图1-2

 3,我们再看看引用类型和值类型的内存分配情况(我们对着代码与图看)

图1-3

图1-4

看了图1-3和图1-4之后,你们可能问我了:你是怎么知道变量在栈中的地址的。嘿嘿,等下教你用c#玩指针

从上面两张图我们可以看出:

①栈的结构是后进先出,也就是说:变量j的生命周期在变量s之前结束,变量s的生命周期在变量i之前结束,

②栈地址从高往底分配

③类型的引用也存储在栈中

二、对于堆和栈的详细介绍,我们往下看。

1,有人老是搞不明白堆和栈的叫法。我来解释下:

堆:在c里面叫堆,在c#里面其实叫托管堆。为什么叫托管堆,我们往下看。

栈:就是堆栈,因为和堆一起叫着别扭,就简称栈了。

2,托管堆:

托管堆不同于堆,它是由CLR(公共语言运行库(Common Language Runtime))管理,当堆中满了之后,会自动清理堆中的垃圾。所以,做为.net开发,我们不需要关心内存释放的问题。

3,有人老是搞不清楚内存堆栈与数据结构堆栈,我们来看看什么是内存堆栈,什么是数据结构堆栈

①数据结构堆栈:是一种后进先出的数据结构,它是一个概念,图4-1中可以看出,栈是一种后进先出的数据结构。

②内存堆栈:存在内存中的两个存储区(堆区,栈区)。

      栈区:存放函数的参数、局部变量、返回数据等值,由编译器自动释放

      堆区:存放着引用类型的对象,由CLR释放

 三、最后我们用c#玩一玩指针

1,首先右键项目-->属性-->生成-->勾选允许不安全代码

2,在写不安全代码的时候需要加上unsafe

    //标记类
    unsafe public class Student
    {
        //标记字段
        unsafe int* pAge;
        //标记方法
        unsafe void getType(int* a)
        {
            //标记代码段
            unsafe
            {
                int* pAbc;      //声明指针语法
            }
        }
    }

  

3,指针的语法

            unsafe
            {
                int* pWidth, pHeight;
                double* pResult;
                byte*[] pByte;
                //&:表示“取地址”,并把一个值数据类型转换为指针,例如,int转换为*int。这个运算称为【寻址运算符】
                //*:表示“获取地址内容”,把一个指针转换为一个值数据类型(例如:*float转换为float)。这个运算符被
                    //称为“间接寻址运算符”(有时称“取消引用运算符”)
                int a = 10;//声明一个值类型,给它赋值10
                int* pA, pB;//声明2个指针
                pA = &a;//取出值类型a的地址,赋值给指针pA
                pB = pA;//把指针pA的地址赋值给pB
                *pB = 20;//获取pB指向的地址内容,并赋值20
                Console.WriteLine(a);//输出20
            }

  

4,将指针强制转化为整数类型(只能转化为uing、long、ulong类型)

int a = 10;
int* pA, pB;
pA = &a;
uint address = (uint)pA;//将指针地址强制转换为整数类型
pB = (int*)address;//将整数类型强制转换为指针
*pB = 20;//指针指向a
Console.WriteLine(a);//输出20

  

5,指针类型的强制装换

int b = 10;
int* pIa;
double* pDa;
pIa = &b;
pDa = (double*)pIa;//将int*强制转换成double*

  

6,void指针(不指向任何数据类型的指针)

int c = 10;
int* pAA;
pAA = &c;
void* pVa = (void*)pAA;//转换viod指针

  

7,指针算数的运算(不允许对void指针进行运算)

int d = 10;
int* pId;//如果地址为100000
pId = &d;
pId++;//结果:100004(int类型的大小为4个字节)

  

8,结构指针:指针成员访问运算符

①指针不能只想任何引用类型
②结构里面不能包含引用类型

MyStruct* pStruct;
MyStruct ms = new MyStruct();
pStruct = &ms;
//--取地址内容赋值为10
(*pStruct).X = 10;
pStruct->X = 10;
//--取地址赋值给pIs
int* pIs1 = &(ms.X);
int* pIs2 = &(pStruct->X);
//结构
struct MyStruct
{
        public int X = 1;
        public int Y = 2;
}

  

9,类成员指针

Person p = new Person();
fixed (int* pIp1 = &(p.X), pIp2 = &(p.Y))
{
}//pIp1和pIp2的生命周期
//类
class Person
{
     public int X;
     public int Y;
}

  

10,有趣的实验

unsafe
{
//有趣的问题:为什么b的值改变了
//回答:因为i的地址指向了b
int a = 10;
int b = 20;
int* i;
i = &a;//将a的地址赋值给指针i
i -= 1;//将i的地址-1(相当于向下移动4个字节(int类型的大小为4个字节))
*i = 30;//取出i指针指向的内容赋值为30
Console.WriteLine(b);//输出30
}

  

时间: 2024-08-10 21:14:27

听起来很吊的堆与栈其实也不过如此的相关文章

Linux C存取效率对照——堆、栈、常量区

本文主要探讨堆和栈在使用中的存取效率.利用宏汇编指令分析訪存情况来进行简单推断. 实验环境及使用工具:i686,32位Ubuntu Linux.gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3,gdb 首先,引用一道题的代码和"答案",这是"比較堆和栈存取效率"的.可是其实,他给的两种方式都用的栈,个人试出来的占用堆空间的情况,仅仅能是malloc()和new()等系统调用产生的. #include<stdio.h> ma

关于堆和栈的那些事

问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么.我仅有高级语言编程经验,没有看过对此更清晰的解释.我的意思是我理解什么是栈,但是它们到底是什么,在哪儿呢(站在实际的计算机物理内存的角度上看)? 在通常情况下由操作系统(OS)和语言的运行时(runtime)控制吗? 它们的作用范围是什么? 它们的大小由什么决定? 哪个更快? 答案一 栈是为执行线程留出的内存空间.当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留

什么是堆和栈

问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么.我仅有高级语言编程经验,没有看过对此更清晰的解释.我的意思是我理解什么是栈,但是它们到底是什么,在哪儿呢(站在实际的计算机物理内存的角度上看)? 在通常情况下由操作系统(OS)和语言的运行时(runtime)控制吗? 它们的作用范围是什么? 它们的大小由什么决定? 哪个更快? 答案一 栈是为执行线程留出的内存空间.当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留

什么是堆和栈,它们在哪儿?

问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么.我仅有高级语言编程经验,没有看过对此更清晰的解释.我的意思是我理解什么是栈,但是它们到底是什么,在哪儿呢(站在实际的计算机物理内存的角度上看)? 在通常情况下由操作系统(OS)和语言的运行时(runtime)控制吗? 它们的作用范围是什么? 它们的大小由什么决定? 哪个更快? 答案一 栈是为执行线程留出的内存空间.当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留

什么是堆和栈,它们在哪儿?(转)

英文原文:What and where are the stack and heap? 问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么.我仅有高级语言编程经验,没有看过对此更清晰的解释.我的意思是我理解什么是栈,但是它们到底是什么,在哪儿呢(站在实际的计算机物理内存的角度上看)? 在通常情况下由操作系统(OS)和语言的运行时(runtime)控制吗? 它们的作用范围是什么? 它们的大小由什么决定? 哪个更快? 答案一 栈是为执行线程留

[转载] - 什么是堆和栈,它们在哪儿?

什么是堆和栈,它们在哪儿? 英文原文:What and where are the stack and heap? 问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么.我仅有高级语言编程经验,没有看过对此更清晰的解释.我的意思是我理解什么是栈,但是它们到底是什么,在哪儿呢(站在实际的计算机物理内存的角度上看)? 在通常情况下由操作系统(OS)和语言的运行时(runtime)控制吗? 它们的作用范围是什么? 它们的大小由什么决定? 哪个更快

“吃人”的那些Java名词:对象、引用、堆、栈

记得中学的课本上,有一篇名为<狂人日记>课文:那时候根本理解不了鲁迅写这篇文章要表达的中心思想,只觉得满篇的"吃人"令人心情压抑:老师在讲台上慷慨激昂的讲,大多数的同学同我一样,在课本面前"痴痴"的发呆. 作为一个有着8年Java编程经验的IT老兵,说起来很惭愧,我被Java当中的四五个名词一直困扰着:对象.引用.堆.栈.堆栈(栈可同堆栈,因此是四个名词,也是五个名词).每次我看到这几个名词,都隐隐约约觉得自己在被一只无形的大口慢慢地吞噬,只剩下满地的衣

JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结--转载http://www.cnblogs.com/kubixuesheng/p/5202561.html

转载自---http://www.cnblogs.com/kubixuesheng/p/5202561.html 俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及到的知识点总结如下: 堆栈是栈 JVM栈和本地方法栈划分 Java中的堆,栈和c/c++中的堆,栈 数据结构层面的堆,栈 os层面的堆,栈 JVM的堆,栈和os如何对应 为啥方法的调用需要栈 属于月经问题了,正好碰上有人问我这类比较基础的知识,无奈我自觉回答不是有效果,现在深入浅出的总结下: 前一篇文章总结了:JV

堆VS栈

c#堆VS栈(Part One) 前言 本文主要是讲解C#语言在内存中堆.栈的使用情况,使读者能更好的理解值类型.引用类型以及线程栈.托管堆. 首先感谢原文作者:Matthew Cochran 为我们带来了一篇非常好的文章,并配以大量图示,帮助我们更好的理解堆栈之间的调用,本文是在作者原文的基础上进行内容上的精简以及加入我个人在这方面的理解和注释. 最后要感谢博客园的田志良,当我搜索堆栈内部使用时,搜索到了作者的文章,吸取了大量有用的知识,而且翻译的也非常好.唯一美中不足的可能是仅仅翻译了Mat