1. a = 0x7fffffff;
b = 0x7fffffff;
c = a + b;
Console.WriteLine("{0}", c);
0x7fffffff是16进制表示的int32的最大数2147483647,0x7 = 0111, a+b会溢出,二进制第一位表示的符号位置1,
c = -2
2. 值和引用的区别
声明一个值类型变量,编译器会在栈上分配一个空间,该空间对应该值类型变量。引用类型的实例分配在堆上,新建一个引用类型实例得到的变量值是该实例在内存中分配的地址。string类型属于特殊的引用类型。C#对string对象做了常量处理,所以内容确定的string实体在堆上只会有一个实例。
c#中的值类型:byte, int, short, long, float, double, decimal, char, bool, struct
引用: string, class, interface, delegate, object
很多时候值类型能减小系统性能开销,但需要进行大量函数参数传递或返回的时候会降低应用程序性能,如果实例被频繁用于HashiTable或ArrayList之类的集合中,这些类会对其中的值类型变量进行装箱操作。
引用对象用Equals比较的是两个对象的引用地址而不是值。值类型不能作为其它任何类型的基类,不能被抽象,不能增加任何新的虚方法,所有方法都是sealed不可重写的。
数组元素不论是引用类型还是值类型都存储在托管堆上。
引用类型在栈中存储一个引用,实际存储位置在托管堆上。
值类型分配在它声明的地方,作为字段时跟随其所属的实例存储,作为局部变量时存储在栈上。
即 值类型是为变量直接在栈上分配了一块内存用于存储数据,引用类型分为两部分,在声明的时候在栈上分配了一块小内存,在new引用类型物体的时候再在堆上分配内存,存储的是该引用在栈中的内存地址。
3. 栈和堆的区别
栈:由编译器自动分配释放,存放函数的参数值,局部变量的值等等。只要栈的剩余空间大于申请的空间,系统就会自动为其分配内存,否则会报异常提示栈溢出。栈是向低地址扩展的数据结构,是一块连续的内存区域。栈顶地址和栈的最大容量都是系统预先规定好的。
堆:一般由程序员分配释放,分配时需指明大小,如果程序员不释放则程序结束时由OS自动回收。操作系统有一个记录空闲地址的链表,当程序申请内存空间的时候,系统会遍历该链表,寻找第一个空间大于申请空间的堆节点,找到后将该节点从空闲地址链表中删除,并且在该内存空间的首地址处记录本次分配的大小,以便在delete操作的时候能够正确的释放本内存空间,由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动将多出来的部分再放回到空闲地址链表中。堆是向高地址扩展的数据结构,是不连续的内存区域。堆的大小受限于操作系统中的有效虚拟内存,所以堆获得的空间比较大也比较灵活。