C变量的作用域,和存储空间分配
- 格式:doc
- 大小:162.50 KB
- 文档页数:18
C语言变量存储类别和内存四区C语言变量存储类别和内存四区C语言是一门通用计算机编程语言,应用广泛。
C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
下面我们一起来看看C语言变量存储类别和内存四区的介绍,欢迎大家阅读!C语言变量存储类别和内存四区变量存储类别变量声明/定义的一般形式:存储类别数据类型变量名存储类别指的是数据在内存中存储的方法。
存储方法分为静态存储和动态存储两大类。
标准C语言为变量、常量和函数定义了4种存储类型:extern、auto、static、register。
根据变量的存储类别,可以知道变量的作用域和存储期。
这4种存储类型可分为两种生存期限:永久的(在整个程序执行期都存在)和临时的(暂时保存在堆栈和寄存器中)。
extern和static用来标识永久生存期限的“变量和函数”,而anto和register用来标识临时生存期限的"变量"。
只有变量才有临时生存期限。
一个变量和函数只能具有一个存储类型,也只能有一种生存期限。
内存中供用户使用的空间有三部分:程序区:存放程序的可执行代码;静态存储区:存放静态变量(全局变量和静态局部变量);动态存储区:存放函数调用时调用函数的现场保护和返回地址、函数形参、自动局部变量;变量的声明分为”定义性声明“(需建立存储空间,如:int a;)和”引用性声明“(不需建立存储空间,如extern a;)。
广义上讲,声明包括定义,一般为叙述方便,把建立存储空间的声明称定义,而不不需建立存储空间的声明称声明。
auto函数中的局部变量,如果不用关键字static加以声明,编译系统对它们是动态地分配存储空间的。
函数的形参和在函数中定义的变量(包括在复合语句中定义的变量)都属此类。
在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中。
在函数调用结束时就自动释放这些空间。
“语言的作用域规则”是一组确定一部分代码是否“可见”或可访问另一部分代码和数据的规则。
C语言中的每一个函数都是一个独立的代码块。
一个函数的代码块是隐藏于函数内部的,不能被任何其它函数中的任何语句(除调用它的语句之外)所访问(例如,用g o t o语句跳转到另一个函数内部是不可能的)。
构成一个函数体的代码对程序的其它部分来说是隐蔽的,它既不能影响程序其它部分,也不受其它部分的影响。
换言之,由于两个函数有不同的作用域,定义在一个函数内部的代码数据无法与定义在另一个函数内部的代码和数据相互作用。
C语言中所有的函数都处于同一作用域级别上。
这就是说,把一个函数定义于另一个函数内部是不可能的。
4.2.1 局部变量在函数内部定义的变量成为局部变量。
在某些C语言教材中,局部变量称为自动变量,这就与使用可选关键字a u t o定义局部变量这一作法保持一致。
局部变量仅由其被定义的模块内部的语句所访问。
换言之,局部变量在自己的代码模块之外是不可知的。
切记:模块以左花括号开始,以右花括号结束。
对于局部变量,要了解的最重要的东西是:它们仅存在于被定义的当前执行代码块中,即局部变量在进入模块时生成,在退出模块时消亡。
定义局部变量的最常见的代码块是函数。
例如,考虑下面两个函数。
整数变量x被定义了两次,一次在func1()中,一次在func2()中。
func1()和func2()中的x互不相关。
其原因是每个x作为局部变量仅在被定义的块内可知。
语言中包括了关键字auto,它可用于定义局部变量。
但自从所有的非全局变量的缺省值假定为auto以来,auto就几乎很少使用了,因此在本书所有的例子中,均见不到这一关键字。
在每一函数模块内的开始处定义所有需要的变量,是最常见的作法。
这样做使得任何人读此函数时都很容易,了解用到的变量。
但并非必须这样做不可,因为局部变量可以在任何模块中定义。
为了解其工作原理,请看下面函数。
这里的局部变量s就是在if块入口处建立,并在其出口处消亡的。
C语言的简答题包含解答共50道题1. 什么是C语言?- C语言是一种通用的高级编程语言,由Dennis Ritchie于1972年开发。
它被广泛用于系统编程和应用程序开发。
2. C语言的主要特点是什么?- C语言具有简洁的语法、高效的性能、直接的硬件访问能力和强大的标准库。
3. 什么是C标准库?-C标准库包含了一组标准的C语言函数,用于执行常见任务,如输入/输出、字符串操作、数学运算等。
4. 如何声明一个变量?-变量的声明通常以数据类型开始,例如:`int myVariable;`5. C语言中有多少个基本数据类型?- C语言有四个基本数据类型,分别是整数、字符、浮点数和指针。
6. 什么是常量?-常量是在程序中固定不变的值,可以用于存储数据或作为计算中的固定值。
7. 如何定义常量?-使用`const`关键字定义常量,例如:`const int myConstant = 10;`8. 什么是变量的作用域?-变量的作用域指的是变量在程序中可见的区域,它可以是全局作用域或局部作用域。
9. 什么是数据类型转换?-数据类型转换是将一个数据类型的值转换为另一个数据类型的过程,通常使用类型转换运算符进行。
10. 什么是条件语句?-条件语句是根据条件执行不同的代码块的语句,通常使用`if`、`else if`和`else`关键字实现。
11. 什么是循环语句?-循环语句用于重复执行一组语句,通常使用`for`、`while`和`do-while`循环。
12. 什么是数组?-数组是一组相同数据类型的元素的集合,通过索引访问。
13. 如何声明和初始化数组?-数组的声明和初始化可以在一行中完成,例如:`int myArray[5] = {1, 2, 3, 4, 5};`14. 什么是字符串?-字符串是字符的序列,通常用于表示文本数据。
15. 如何声明和初始化字符串?-使用字符数组来声明和初始化字符串,例如:`char myString[] = "Hello";`16. 什么是指针?-指针是一个变量,存储了一个内存地址,可以用于访问该地址处的数据。
一.C语言中,从变量的作用域角度来分,可以分为全局变量和局部变量。
二.变量值存在的时间角度来分,可以分为静态存储方式和动态存储方式。
所谓静态存储方式是指在程序运行期间有系统分配固定的存储空间的方式。
而动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。
具体包含4种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。
1. 自动的(auto)在调用函数时系统会给他们分配存储空间,在函数调用结束时就自动释放这些存储空间,这类局部变量称为自动变量。
2. 静态的(static)为了满足局部变量的值在函数调用结束后不消失而且保留原值,既占用的存储单元不释放,就出现了静态的局部变量,用static来声明的局部变量。
局部变量的特点:(1)相对自动变量(即动态局部变量),在程序的运行期间都占用静态存储区,直到程序结束才释放该存储区。
(2)静态局部变量只是在程序编译时赋初值,以后每次调用时不再重新赋初值,而只是保留上次函数调用结束时的值。
动态局部变量编译时不赋初值,直到程序调用时才给变量赋值,每次调用都要赋初值。
(3)在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时会自动赋初值0或空字符。
而对动态局部变量,不赋初值则它的值是一个不确定的值,因为动态变量每次都要自动分配存储空间,存储空间的值是不固定的。
(4)静态局部变量在函数调用结束后不释放,但其他函数是不能调用的。
3.寄存器的(register)为了提高程序的执行效率,对一些运算频繁的变量定义为寄存器变量可以节省每次程序执行时的内存读取,大大节省了时间,提高了效率。
寄存器的一些特点:(1)寄存器变量的特点程序运行时分配寄存器存储空间,结束时释放。
这个特点限定了只能把局部自动变量和形式参数定义为寄存器变量。
(2)局部静态变量不能定义为寄存器变量。
4. 外部的(extern)外部变量是在函数的外部定义的全局变量,他的作用是从变量的定义初开始,到本程序文件的末尾。
C变量的作用域,和存储空间分配1.C变量的作用域2.变量修饰符3.动态分配内存4.C变量的存储空间实现机制5.字节对齐.一.概述C变量的作用域C的变量作用域是指一个变量在一个程序中能被有效访问范围.按范围来划分,分为变量的作用域分为局部、全局、文件三种范围.变量的作用域都是通过它在程序中的位置隐式说明的。
因此开发者必须对变量的作用域有所了解.变量的存储变量是对程序中数据的存储空间的抽象,变量存储包括两种情况,一种是被链接器链接成可执行程序后,变量在可执行程序文件里所占的空间.一种是运行后变量在内存所占空间的分布.两种情况要分开讨论.前者我们称为存储态,后者称为运行态.两者有共同点也有区别,在后面将分开讨论.C变量的作用域属于C语言的语法问题,所有标准C程序都遵循相同规则.如果错误的使用常造成无法编译通过.但是讨论变量存储不能脱离CPU,操作系统和编译器的类型来谈,特别对需要经常在不同操作系统下编程的开发者.但是此类问题有一定共性.为方便讨论,后文均指32位CPU和Windows 操作系统.对变量的存储理解不清楚,最常犯的错识就是对不能修改的字符串区进行修改造成程序崩溃.二.变量的作用域C的变量作用域是指一个变量在一个程序中能被有效访问范围.按范围来划分,分为变量的作用域分为局部、全局、文件三种范围.1.局部作用域声明在函数内部的变量都是局部作用域,无法被其他函数的代码所访问。
函数的形式参数的作用域也是局部的,它们的作用范围仅限于函数内部所用的语句块。
还有一种特殊是函数中的用{}包括语句块定义变量也是局部作用域,而且只在语法里有效.上面例子里的三个num变量都是局部变量,只在本身函数里可见。
,在两个函数出现同名的变量不会互相干扰。
但同一函数定义同名变量,最内层会覆盖外层同名变量(上例中红色num 会覆盖蓝色num,在执行完语法块后,红色num失效,程序对num的引用又变成了对函数参数的引用).所以上面的两个输出,在主函数里仍然是5,在add()函数里输出是1,6。
2.全局作用域对于具有全局作用域的变量,我们可以在程序的任何位置访问它们。
当一个变量是在所有函数的外部声明,那么这个变量就是全局变量。
add()里的num修改是局域变量.对main中的全局变量num不影响.因此输出是6,36.文件作用域文件作用域是指外部标识符仅在声明它的同一个转换单元内的函数汇总可见。
所谓转换单元是指定义这些变量和函数的源代码文件(包括任何通过#include指令包含的源代码文件)。
static存储类型修饰符指定了变量具有文件作用域。
换句话说,在一个源码文件里的用static修饰的变量和函数,只能被同一个源码文件里的函数所引用/调用.这在没有private和protected关键字的C语言里,用static是实现数据封装,防止被外部程序改动的一种主要手段,大量在程序中被采用.上面的程序中变量num和函数add()在声明是采用了static存储类型修饰符,这使得它们具有文件作用域,仅在定义它们的文件内可见。
●局域变量是指定义:在函数内定义,只在本函数内有效●main中定义的变量只在main中有效●不同函数中同名变量,占不同内存单元●形参属于局部变量●可定义在复合语句中有效的变量●局部变量可用存储类型:auto register static (默认为auto)●全局变量---外部变量:在函数外定义,可为本文件所有函数共用●有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件●外部变量声明:extern 数据类型变量表;●外部变量定义与外部变量说明不同,●定义是产生实际效果的语句,在整个项目里,同名的全局变量只能定义一次,外部变量声明只是说明全局变量的类型和名字,可以出现多次.●外部变量可用存储类型:缺省或static外部变量定义与说明上面两个例子运行结果都是一样,只是显示如何通过extern 来扩大全局的使用范围.另外一个重要一点是.extern 只是声明,不产生实际空间,因此对其声明变量赋初值是有编译错误的.extern int a=1; /* 错误,编译器会产生编译错误*/按软件工程学的观念,全局应该少用,因为他会带来许多问题✡全局变量在程序全部执行过程中占用存储单元✡降低了函数的通用性、可靠性,可移植性✡降低程序清晰性,容易出错三.变量的存储修饰符各种变量的作用域不同,本质上是因为变量存储类型不同.主要是指运行态时存储占用内存空间的方式.变量的存储方式可分为”静态存储”和”动态存储”两种.静态存储变量通常是指在变量定义时就分布存储单元并一直保持不变.直至整个程序结束.比如上面所说的全局变量.动态存变量是在程序执行过程中,使用时才分配存储单元,使用完毕立即释放.典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,只是函数被调用时才以分配,调用函数完毕立即释放.如果一个函数被多次调用,则反复地分配,释放形参变量的存储单元.静态存储变量是在程序运行时是一直存在的,而动态存储变量则时而存在时面消失.这种由于存储方式产生不同而产生存在时间不同的特性称为变量的生存期.生存期表示变量存在的时间范围.生存期和作用域是从时间和空间这两个不同角度来描述变量的特性,这两者即有联系,又有区别.一个变量究竟属于哪一种存储方式,并不能仅仅从它的作用域来判断,还应有明确的存储类型声明.在C语言,对变量的存储类型声明有以下4种●自动(auto)、●静态(static)、●外部(extern)、●寄存器(regiser)。
其中auto,register 属于动态存储方式,extern变量和static变量属于静态存储试式.1.自动存储类型(auto)自动存储类型修饰符指定了一个局部变量为自动的,这意味着,每次执行到定义该变量的语句块时,都将会为该变量在内存中产生一个新的拷贝,并对其进行初始化。
实际上,如果不特别指明,局部变量的存储类型就默认为自动的,因此,加不加auto都可以。
main(){auto int num=5; /* 等于int num=5;*/printf("%d\n",num);}在这个例子中,不论变量num的声明是否包含关键字auto,代码的执行效果都是一样的。
函数的形式参数存储类型默认也是自动的。
2.静态存储变量(static)前面已经使用了static关键字,但是对于局部变量,静态存储类型的意义是不一样的,这时,它是和自动存储类型相对而言的。
静态局部变量的作用域仍然近局限于声明它的语句块中,但是在语句块执行期间,变量将始终保持它的值。
而且,初始化值只在语句块第一次执行是起作用。
在随后的运行过程中,变量将保持语句块上一次执行时的值。
上面两个源文件,只有函数add()里的变量声明有所不同,一个是自动存储类型,一个是静态存储类型。
对于1.C 文件,输出结果为51 51 51;这很好理解,每次初始值都是50,然后加1上来。
对于2.C 文件,输出结果为51 52 53;这是由于变量是静态的,只在第一次初始化了50,以后都是使用上次的结果值。
当第一次调用add()时,初始化为50,然后加1,输出为51;当第二次调用时,就不初始化了,这时num 的值为上次的51,然后加1,输出52;当第三次调用时,num 为52,加1就是53了。
在局部变量的定义前加上static 标识符就构成静态局域变量.静态局域变量有如下特点,它有如下特点:● 静态局部变量在函数内定义,但不像自动变量一样,当调用时就存在,退出函数时就消失. 静态局部变量始终存在,也就是说它的生存期为整个源程序● 静态局部变量的生存期虽然为整个源程序,但是其作用域与自动变量相同,即可能在定义该变量的的函数内使用该变量.退出该函数后,尽管该变量还继续存在,但不能使用它● 允许对静态局域变量赋初值,若未赋初值,则系统自动赋以0值在全局变量定义前加上static 标识符就构成了静态全局变量.他与非静态的全局变量的最大区别是静态全局变量作用域是当前源程序.而全局变量作用域是整个源程序3.外部存储类型(extern)外部存储类型声明了程序将要用到的、但尚未定义的外部变量。
通常,外部存储类型都是用于声明在另一个转换单元中定义的变量。
这在前一节已经解释过.外部变量的声明既可以在引用它的函数的内部,也可以在外部。
如果变量声明在函数外部,那么同一转换单元内的所有函数都可以使用这个外部变量。
反之,如果在函数内部,那么只有这一个函数可以使用该变量。
4.寄存器存储类型(register)被声明为寄存器存储类型的变量,除了程序无法得到其地址外,其余都和自动变量一样。
使用寄存器存储类型的目的是让程序员指定某个局部变量存放在计算机的某个硬件寄存器里而不是内存中,以提高程序的运行速度。
不过,这只是反映了程序员的主观意愿,编译器可以忽略寄存器存储类型修饰符。
寄存器变量的地址是无法取得的,因为绝大多数计算机的硬件寄存器都不占用内存地址。
而且,即使编译器忽略寄存器类型修饰符把变量放在可设定地址的内存中,我们也无法取地址的限制仍然存在。
关于寄存器变量的说明:● 只有局部自动变量和形式参数才可以定义为寄存器变量,因为寄存器变量属于动态存储方式.凡需要采用静态存储方式的的变量不能定义为寄存器变量● 在某一些C 编译器中,如Turbo C,MS C 中,实际上把寄存器变量当成自动变量处理,因此程序的运行速度并不能提高,在程序中允许使用寄存器变量只是为了与标准C 保持一致● 即使能真正使用寄存器变量的机器,由于CPU 的寄存器的个数是有限的,因此使用寄存器变量的个数也是有限的.并不是程序使用register ,编译器就一定会把它编译成寄存器变量.● 在现代的C 编译器,优化已经做得相当出色了,需要优化地方基本上会自动优化.纯粹为了提高运行速度.用register 显得多余.四.动态内存分配在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?在很多的情况下,你并不能确定要使用多大的数组.即便是你的程序在运行时就申请了固定大小的你认为足够大的内存空间。
但是如果因为某种特殊原因人数有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。
这种分配固定大小的内存分配方法称之为静态内存分配。
但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。
那么有没有其它的方法来解决这样的外呢体呢?有,那就是动态内存分配。
所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。
动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。