C语言变量类型与内存
来源:互联网 发布:淘宝店铺首页全屏大图 编辑:程序博客网 时间:2024/05/16 14:21
摘录:http://www.cppblog.com/oosky/archive/2006/01/21/2958.html
http://www.cnblogs.com/mjios/archive/2013/03/21/2973719.html
C语言有丰富的数据类型和运算符,因此计算能力非常强大,计算过程中使用的值一般用变量来存储。变量也是有分类型的,不同类型的变量有不同的存储类型、不同的生命周期、不同的作用域,C语言也提供了一些关键字来设置变量的属性(比如设置存储类型、生命周期)。
一、变量的作用域
C语言根据变量作用域的不同,将变量分为局部变量和全局变量。
1.局部变量
- 定义:在函数内部定义的变量,称为局部变量。形式参数也属于局部变量。
- 作用域:局部变量只在定义它的函数内部有效,即局部变量只有在定义它的函数内部使用,其它函数不能使用它。
2.全局变量
- 定义:在所有函数外部定义的变量,称为全局变量。
- 作用域:全局变量的作用范围是从定义变量的位置开始到源程序结束,即全局变量可以被在其定义位置之后的其它函数所共享。
int a;//全局变量int main () { int b;//局部变量 }
根据变量定义地方不同,决定了该变量的作用范围,因此有了局部和全局之分。
二、变量的生命周期
C语言根据变量的存储类型的不同,可以把变量分为:自动变量、静态变量、寄存器变量。变量的存储类型决定了变量何时创建、何时销毁以及它的值能保持多久,也就是决定了变量的生命周期。
1.自动变量
- 定义:被关键字auto修饰的局部变量都是自动变量,但是极少使用这个关键字,基本上是废的,因为所有的局部变量在默认情况下都是自动变量。
- 生命周期:在程序执行到声明自动变量的代码块(函数)时,自动变量才被创建;当自动变量所在的代码块(函数)执行完毕后,这些自动变量就会自行销毁。如果一个函数被重复调用,这些自动变量每次都会重新创建。
void test(int a, int b) { int c = a + b; auto int d; }
函数中的形参ab,变量中定义的cd都是局部变量。
2.静态变量
- 定义:所有的全局变量都是静态变量,或被关键字static修饰的局部变量也是静态变量。
- 生命周期:静态变量在程序运行之前创建,在程序的整个运行期间始终存在,直到程序结束。
#include <stdio.h> int a; void test() { static int b = 0; b++; int c = 0; c++; printf("b=%d, c=%d \n", b, c); } int main() { int i; // 连续调用3次test函数 for (i = 0; i<3; i++) { test(); } return 0; }
第3行的变量a、第6行的变量b都是静态变量,第9行的变量c、第16行的变量i是自动变量。
因为第6行的变量b是静态变量,所以它只会被创建一次,而且生命周期会延续到程序结束。因为它只会创建一次,所以第6行代码只会执行一次,下次再调用test函数时,变量b的值不会被重新初始化为0。
注意:虽然第6行的变量b是静态变量,但是只改变了它的存储类型(即生命周期),并没有改变它的作用域,变量b还是只能在test函数内部使用。
输出结果:
b=1,c=1b=2,c=1b=3,c=1
3.寄存器变量
- 定义:被关键字register修饰的自动变量都是寄存器变量;只有自动变量才可以是寄存器变量,全局变量和静态局部变量不行;寄存器变量只限于int、char和指针类型变量使用;
- 生命周期:因为寄存器变量本身就是自动变量,所以函数中的寄存器变量在调用该函数时占用寄存器中存放的值,当函数结束时释放寄存器,变量消失。
int main() { register int a; return 0; }
注意:由于计算机中寄存器数目有限,不能使用太多的寄存器变量。如果寄存器使用饱和时,程序将寄存器变量自动转换为自动变量处理
为了提高运算速度,一般会将一些频繁使用的自动变量定义为寄存器变量,这样程序尽可能地为它分配寄存器存放,而不用内存
三、变量与内存
变量定义方式的不同,其在内存中的保存方式也不相同,在程序中也体现为不同的作用域和生命周期。
有3个地方可以用于存储变量:普通内存(静态内存)、运行时堆栈(动态内存)、硬件寄存器。
1.堆栈
自动变量是存储在堆栈中的。
申请方式
1.栈: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
2.堆: 需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = (char *)malloc(10);
但是注意p1、p2本身是在栈中的。堆和栈的区别
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表申请后系统的响应
1.栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
2.堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。申请大小的限制
1.栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
2.堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。申请效率的比较
1.栈由系统自动分配,速度较快。但程序员是无法控制的。
2.堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.堆和栈中的存储内容
1.栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
2.堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。总结
局部变量定义后,便存入堆栈。比如函数开始时,首先会将下一执行语句执行地址入栈,接着形参入栈(从右往左),接着是函数中的局部变量(静态变量不入栈)。函数执行结束后,便按后进先出的原则,局部变量、形参逐个出栈,直到最后栈顶指针指向最开始存的下一语句执行地址,程序继续。
由此可以理解看出,程序的运行本质就是对内存的操作,而不同的内存存储发式决定了程序的执行方式。
一般自定义的局部变量存于栈;由程序员申请创建的内存空间的,如使用malloc
,存于堆。
栈的地址是连续的,而堆是用链表来存储的空闲内存地址的,自然是不连续的。栈是一种线性结构,堆是一种链式结构,是两种不同的动态数据区。
进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干
├———————┤高端内存区域
│ …… │
├———————┤
│ 栈│ 向低地址扩展
├———————┤
│ …… │
├———————┤
│
├———————┤
│ 堆│ 向高地址扩展
├———————┤
│ …… │
├———————┤低端内存区域
2.静态内存
静态变量是存储在静态内存中的,也就是不属于堆栈。
静态变量的生命周期贯穿整个程序, 程序结束后由系统释放。
例子:
//main.cpp int a = 0; //全局初始化区 char *p1; //全局未初始化区 main() { int b; //栈 char s[] = "abc";// 栈 char *p2; //栈 char *p3 = "123456"; //123456\0在常量区,p3在栈上。 static int c =0; //全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区,但是注意p1、p2本身是在栈中的 strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 }
3.硬件寄存器
寄存器变量存储在硬件寄存器中,比存储在内存中的变量访问效率更高。
- C语言变量类型与内存
- 【C语言】06-变量与内存
- 【02-C语言】06-变量与内存
- C语言入门教程6-变量与内存
- C语言变量与内存分配
- C语言指针背景--变量与内存
- C语言变量类型
- C语言--变量类型
- C语言变量类型
- C语言-变量类型
- C语言变量类型
- C语言变量类型
- C语言变量类型
- C语言 变量类型
- 从内存理解c语言中变量的存储类型
- 从内存理解c语言中变量的存储类型
- 从内存理解c语言中变量的存储类型
- 从内存理解c语言中变量的存储类型
- Android Activity启动模式(launchMode)
- 利用属性动画将Button变宽
- 抓取网页数据并解析
- android学习日记02-安装androidstudio完成helloword
- eclipse 设置默认编码为Utf-8 详细教程。
- C语言变量类型与内存
- 22. Generate Parentheses
- spring 对于hibernate操作的封装 HibernateCallback接口的学习
- Canvas绘图
- Qt之QTextCodec乱谈
- https server with openssl 笔记
- vector<vector<Point>>contours; vector<Vec4i>hierarchy;
- “匠人精神”6大内涵:德国登峰造极制造业的成功秘诀
- callback(回调函数)