C语言变量的存储类别
C语言第5章 函数(数组作参数、变量的作用域和存储类别)

int large(int x, int y) {
int flag; if (x > y) {
flag = 1; } else if (x < y) {
flag = -1; } else {
flag = 0; } return (flag); }
⒉ 数组名可作函数参数
数组名作参数,此时实参与形参都应用数组名。
printf(“%d”, a[i]); }
return 0; }
a[0] a[1] a[2] a[3] a[4]
36194
b[0] b[1] b[2] b[3] b[4]
void sort(int b[ ], int n) {
int i, j, k, t; for (i=0; i<=n-2; i++)
(3) 形式参数也是局部变量。 例如: char f2(int x,int y) {
int i,j; …… }
⒋ 在一个函数内部,可以
在复合语句中定义变量,这
些变量 只在本复合语句中
有效,离开复合语句该变量
就无效,释放内存单元。这
种复合语句也可称为“分程
序”或“程序块”。
#include <stdio.h>
int a=3,b=5;
int max(int a,int b)
{ int c; c=a>b?a:b;形参a、b的作 用范围
return(c);
}
int main(void) {
局部变量
int a=8;
a的作用
printf(“max=%d”,max(a,b)); 范围 return 0;
}
全局变量a、b 的作用范围
C中的auto、static、register和extern的区别

} int A=13,B=-8;
也可以在多文件的程序中声明外部变量。
extern还可声明函数,eg:extern int fun(int a, int b);声明的外部函数可供其他文件调用,在C中,定义函数时省略extern,则隐含为外部函数 另附加一个两个关键字const和volitate
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
auto变量:函数中的局部变量,如不专门声明static,一般都是动态地分配存储空间。自动变量:在调用该函数时系统会给他们分配存储空间,一旦函数调用结束这些存储空间就会自动释放。关键字“auto”可以省略,不写则隐含确定为“自动存储类别”,属于动态存储方式。
C语言函数章节选择题

1.在C语言中,全局变量的存储类别是:A) static B) externC) void D) registerA2.C语言中,凡未指定存储类别的局部变量的隐含存储类别是:A) 自动(auto) B) 静态(static)C) 外部(extern) D) 寄存器(register)A3. 在一个C源程序文件中,要定义一个只允许本源文件中所有函数使用的全局变量,则该变量需要使用的存储类别是:________。
A) extern B) registerC) auto D) staticD4. 若有以下调用语句,则正确的fun函数首部是main(){ ∶∶int a;float x;∶∶fun(x,a);∶∶}A) void fun(int m,float x) B) void fun(float a,int x)C) void fun(int m,float x[]) D) void fun(int x,float a)B5. 有如下函数调用语句func(rec1,rec2+rec3,(rec4,rec5));该函数调用语句中,含有的实参个数是A) 3 B) 4C) 5 D) 有语法错误A6. 以下程序的运行结果是。
#include <stdio.h>main(){ int k=4,m=1,p;p=func(k,m); printf("%d, ",p);p=func(k,m); printf("%d\n",p); }func(int a,int b){ static int m=0,i=2;i+=m+1;m=i+a+b;return m; }A) 8,17, B) 8,17C) 8,8 D) 4,1B7. 函数fun的功能是:根据以下公式计算S,n通过形参传入,n的值大于等于0。
划线处应填________。
1 1 1 1S=1 - ─+ ─- ─+ …───3 5 7 2n-1float fun(int n){ float s=0.0,w,f=-1.0;int i=0;for(i=0;i<=n;i++){________;w=f/(2*i+1);s+=w; }return s; }A) f=1 B) f=-1C) f=-1*f D) f=0C8. 函数fun的功能是:根据以下公式计算并返回S,n通过形参传入,n的值大于等于0。
第18讲 局部变量 全局变量和存储分类 局部变量作用域和生存期

局部变量 全局变量和存储分类 局部变量及其作用域和生存期
第八章 用户标识符的作用域和存储类
8.1 局部变量,全局变量和存储分类
1. 用户标识符的作用域 作用域 在C语言中,由用户命名的标识符都有一个有 效的作用域.所谓"作用域"是指程序中的某一 部分,只有在这一部分中,该标识符才是有定义 的,即只有在这个域中才能使用该标识符. 例如,在某一函数内定义的变量,只能在该 函数内进行使用.显然,变量的作用域与其定义 语句在程序中出现的位置有直接的关系.由此可 以划分为局部变量和全局变量.
2. 局部变量 例 不同函数中同名变量 例 复合语句中变量
Ch7_103.c Ch7_102.c
局部变量 float f1(int a) 5 #define N { main() int b,c; 定义:在函数内定义,只在本函数内有效 main() a,b,c有效 a,b; { int{ …….i; 说明: } int a=3; int a[N]={1,2,3,4,5}; b=4; ①在main函数中定义的变量只能在main函数中有效 printf("main:a=%d,b=%d\n",a,b); char f2(int x,int y) for(i=0;i<N/2;i++) ②不同函数中的同名变量,占不同的内存单元 sub(); i,j; temp; { { int int x,y,i,j有效 printf("main:a=%d,b=%d\n",a,b); ③函数的形参属于局部变量 …… temp=a[i]; } } ④可以定义只在某个复合语句中有效的变量 a[i]=a[N-i-1]; sub() main() a[N-i-1]=temp; { int a,b;m,n; { int } m,n有效 a=6;……. b=7; for(i=0;i<N;i++) } printf("sub:a=%d,b=%d\n",a,b); printf("%d ",a[i]); } }
c语言中变量的存储类别

一.C语言中,从变量的作用域角度来分,可以分为全局变量和局部变量。
二.变量值存在的时间角度来分,可以分为静态存储方式和动态存储方式。
所谓静态存储方式是指在程序运行期间有系统分配固定的存储空间的方式。
而动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。
具体包含4种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。
1. 自动的(auto)在调用函数时系统会给他们分配存储空间,在函数调用结束时就自动释放这些存储空间,这类局部变量称为自动变量。
2. 静态的(static)为了满足局部变量的值在函数调用结束后不消失而且保留原值,既占用的存储单元不释放,就出现了静态的局部变量,用static来声明的局部变量。
局部变量的特点:(1)相对自动变量(即动态局部变量),在程序的运行期间都占用静态存储区,直到程序结束才释放该存储区。
(2)静态局部变量只是在程序编译时赋初值,以后每次调用时不再重新赋初值,而只是保留上次函数调用结束时的值。
动态局部变量编译时不赋初值,直到程序调用时才给变量赋值,每次调用都要赋初值。
(3)在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时会自动赋初值0或空字符。
而对动态局部变量,不赋初值则它的值是一个不确定的值,因为动态变量每次都要自动分配存储空间,存储空间的值是不固定的。
(4)静态局部变量在函数调用结束后不释放,但其他函数是不能调用的。
3.寄存器的(register)为了提高程序的执行效率,对一些运算频繁的变量定义为寄存器变量可以节省每次程序执行时的内存读取,大大节省了时间,提高了效率。
寄存器的一些特点:(1)寄存器变量的特点程序运行时分配寄存器存储空间,结束时释放。
这个特点限定了只能把局部自动变量和形式参数定义为寄存器变量。
(2)局部静态变量不能定义为寄存器变量。
4. 外部的(extern)外部变量是在函数的外部定义的全局变量,他的作用是从变量的定义初开始,到本程序文件的末尾。
你知道嵌入式C语言中各变量存储的位置吗?

你知道嵌入式C语言中各变量存储的位置吗?
在举行C/C++编程时,需要程序员对内存的了解比较精准。
常常需要操作的内存可分为以下几个类别:
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局
部变量的值等。
其操作方式类似于数据结构中的栈。
2、堆区(heap)—普通由程序员分配释放,若程序员不释放,程序
结束时可能由OS回收。
注重它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放
在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
4、文字常量区—常量字符串就是放在这里的。
5、程序代码区—存放函数体的二进制代码。
以下是一段实际解释的程序代码:这是一个前辈写的,十分具体。
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456在常量区,p3在栈上。
static int c =0;全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3
第1页共3页。
C程序设计 变量作用域和存储类别(教案)

4、函数调用
5、本章总结
备注
思主要区别是什么?
函数的嵌套与递归调用的实现过程是怎样的?
结合前面所学知识,试全面总结变量的分类及作用。
教学后记
课题
变量作用域和存储类别
课型
理论课
教学时数
2
教学目的
掌握变量作用域、生命期
重点难点
静态存储变量
采用教法
启发式教学,
学法建议
讨论交流、比较
教学
过程
设计
(复习内容、课题引入、主要知识点序列或操作步骤教法设计、时间分配等)
1、复习函数定义、调用、参数传递方式,提出各个函数同名变量问题,进而引入变量作用域概念
2、变量的作用域(有效范围、可见性)
变量的作用域:变量的有效范围或者变量的可见性。变量定义的位置决定了变量的作用域。
变量从作用域(变量的有效范围,可见性)的角度可以分为:局部变量,全局变量。
1、变量的存储类别(生存期、生命期)
变量从空间上分为局部变量、全局变量。
从变量存在的时间的长短(即变量生存期)来划分,变量还可以分为:动态存储变量、静态存储变量。变量的存储方式决定了变量的生存期。
C语言变量的声明和空间的分配

无论用什么语言编制的程序,都是为让计算机完成某一特定功能而编写的文本文件。
这些文本文件是不能直接在机器上运行的,它们必须经过系统软件(包括编辑器和编译器)的输入并编译或汇编后,转换成二进制的可执行代码,才是计算机可以识别的机器语言。
此时,程序就是一个包含二进制可执行代码文件的模块。
当内核把二进制的可执行代码装入内存后,它由三部分组成:代码段、数据段、堆栈段。
在线性地址的低地址字段是代码段,存放程序经编译后的可执行代码(程序文本)。
在操作系统中,代码段是只读的,不能修改,所以,代码段的长度是不会改变的。
在程序文本(代码段)的上方是数据段,用来存放程序的变量、字符串和其它数据。
它分为初始化静态数据(data)和未初始化静态数据(BSS。
数据段的长度是可以改变的。
程序可以修改其中的变量。
在程序设计中,将其值可以改变的量称为变量。
每一个变量在内存中都要占据一定的存储单元,因此,每一个变量也就会具有一定的存储属性。
从变量的作用域(空间)的角度来考虑变量的属性,可将变量分为全局变量和局部变量。
局部变量局部变量是指在一个函数内部定义的变量,它只中本函数范围内有效。
说明:1、在主函数中定义的变量只在主函数中有效,且主函数也不能使用其他函数中定义的变量2、在不同函数中可以使用相同名字的变量,它们代表不同的变量,互不干扰;3、形参也是局部变量,也只在对应的函数中有效,其他函数不能使用4、在一函数内部,可在复合语句(有一个{} 括起的一组语句)中定义变量,这些变量只在本复合语句中有效。
全局变量程序的编译单位是源程序文件,一个源文件可以包含一个或若干个函数。
在函数之外定义的变量称为外部变量(extern ), 也叫全局变量。
全局变量的有效范围是从定义变量的位置开始到本源程序文件结束为止,其关键字extern 可以省略。
说明:1、在一个函数中既可以使用本函数中的局部变量,又可以使用有效的全局变量。
2、设置全局变量的作用是增加函数间数据联系的渠道。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C语言变量的存储类别内存中供用户使用的存储空间分为代码区与数据区两个部分。
变量存储在数据区,数据区又可分为静态存储区与动态存储区。
静态存储是指在程序运行期间给变量分配固定存储空间的方式。
如全局变量存放在静态存储区中,程序运行时分配空间,程序运行完释放。
动态存储是指在程序运行时根据实际需要动态分配存储空间的方式。
如形式参数存放在动态存储区中,在函数调用时分配空间,调用完成释放。
对于静态存储方式的变量可在编译时初始化,默认初值为O或空字符。
对动态存储方式的变量如不赋初值,则它的值是一个不确定的值。
在C语言中,具体的存储类别有自动(auto)、寄存器(register)、静态(static)及外部(extern)四种。
静态存储类别与外部存储类别变量存放在静态存储区,自动存储类别变量存放在动态存储区,寄存器存储类别直接送寄存器。
变量存储类别定义方法:存储类别类型变量表;例如:(1)a,b,c为整型自动存储类别变量:auto int a,b,c;(2)x,y,z为双精度型静态存储类别变量:static double x,y,z;1、变量有哪些存储类型?变量的存储类型由“存储类型指明符”来说明。
存储类型指明符可以是下列类键字之一:autoregisterexternstatic下面是详细的解释:auto 存储类指明符--用于说明具有局部作用域的变量,它表示变量具有局部(自动)生成期,但由于它是所有局部作用域变量说明的缺省存储类指明符,所以使用得很少。
要注意的是,所有在函数内部定义的变量都是局部变量,函数内部定义的变量其作用域只在函数内部。
它的生存期为该函数运行期间,一旦离开这个函数或这个函数终止,局部变量也随之消失。
register 存储类指明符--当声明了这个指明符后,编译程序将尽可能地为该变量分配CPU内部的寄存器作为变量的存储单元,以加快运行速度。
注意,寄存器与存储器是不同的。
寄存器一般在CPU内部,而存储器一般指外部的(比如内存条),CPU内部的寄存器其运算速度是很高的。
当寄存器已分配完毕,就自动地分配一个外部的内存。
它的作用等价于auto,也只能用于局部变量和函数的参量说明。
static 存储类指明符--表示变量具有静态生成期。
static变量的的特点是它离开了其作用域后,其值不会消失。
当回到该作用域之后又可以继续使用这个static变量的值。
例:利用static变量统计调用函数的次数int two(); /*函数原型说明*/void main(){int a=0;a=two(); /*a的值等于1*/a=two() /*a的值等于2*/a=two(); /*a的值等于3*/}int two(){static int b=0;/*定义了一个局部的static变量*/b ;return b;}如果不是一个static变量就不会有这个效果了int two(); /*函数原型说明*/void main(){int a=0;a=two(); /*a的值等于1*/a=two() /*a的值等于1*/a=two(); /*a的值等于1*/}int two(){int b=0;b ;return b;}变量a的值总是1,原因是在函数two()中,变量b不是一个static变量,其值随着离开two函数就消失了,当回到two函数时又被重新赋值0。
extern 存储类指明符--一般用在工程文件中。
在一个工程文件中因为有多个程序文件,当某一个变量在一个程序文件中定义了之后,如果在另一个程序文件中予以定义,就会出现重复定义变量的错误。
使用extern存储类型指明符就可以指出在该文件外部已经定义了这个变量。
extern变量的作用域是整个程序。
2、变量存储在内存的什么地方?1)变量可以存储在内存的不同地方,这依赖于它们的生成期。
在函数上部定义的变量(全局变量或static外部变量)和在函数内部定义的static变量,其生存期就是程序运行的全过程。
这些变量被存储在数据段(Data Segment)中。
数据段是在内存中为这些变量留出的一段大小固定的空间,它分为二部分,一部分用来初始化变量,另一部分用来存放未初始化的变量。
2)在函数内部定义的auto变量(没有用关键字static定义的变量)的生成期从程序开始执行其所在的程序块代码时开始,到程序离开该程序块时为止。
作为函数参数的变量只在调用该函数期间存在。
这些变量被存储在栈(stack)中。
栈是内存中的一段空间,开始很小,以后逐渐自动变大,直到达到某个预定义的界限。
3)当用malloc等函数给指针分配一个地址空间的时候,这个分配的内存块位于一段名为“堆(heap)”的内存空间中。
堆开始时很小,但调用malloc或clloc等内存分配函数时它就会增大。
堆可以和数据段或栈共用一个内存段,也可以有它自己的内存段,这完全取决于编译选项和操作系统。
与栈相似,堆也有一个增长界限,并且决定这个界限的规则与栈相同。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------C语言变量的作用域和存储类型一、作用域和生存期C程序的标识符作用域有三种:局部、全局、文件。
标识符的作用域决定了程序中的哪些语句可以使用它,换句话说,就是标识符在程序其他部分的可见性。
通常,标识符的作用域都是通过它在程序中的位置隐式说明的。
1.局部作用域前面各个例子中的变量都是局部作用域,他们都是声明在函数内部,无法被其他函数的代码所访问。
函数的形式参数的作用域也是局部的,它们的作用范围仅限于函数内部所用的语句块。
void add(int);main(){int num=5;add(num);printf("%d\n",num); /*输出5*/}void add(int num){num++;printf("%d\n",num); /*输出6*/}上面例子里的两个num变量都是局部变量,只在本身函数里可见。
前面我们说了,在两个函数出现同名的变量不会互相干扰,就是这个道理。
所以上面的两个输出,在主函数里仍然是5,在add()函数里输出是6。
2.全局作用域对于具有全局作用域的变量,我们可以在程序的任何位置访问它们。
当一个变量是在所有函数的外部声明,也就是在程序的开头声明,那么这个变量就是全局变量。
void add(int);int num;main(){int n=5;add(n);printf("%d\n",num); /*输出6*/}void add(num) /*形式参数没有指定类型*/{num++;printf("%d\n",num); /*输出6*/}上面的main()和add()里面,并没有声明num,但是在最后输出的时候却要求输出num,这是由于在程序的开始声明了num是全局变量,也就是在所有函数里都可以使用这个变量。
这时候一个函数里改变了变量的值,其他函数里的值也会出现影响。
上面的例子输出都是6,因为在add()函数里改变了num的值,由于num是全局变量,就好象它们两个函数共用一个变量,所以在main()函数里的num也随之改变了。
3.文件作用域在很多C语言书上,都没有说明文件作用域,或者只是略微的提到,其实文件作用域在较大程序中很有作用(在多文件系统中)。
文件作用域是指外部标识符仅在声明它的同一个转换单元内的函数汇总可见。
所谓转换单元是指定义这些变量和函数的源代码文件(包括任何通过#i nclude指令包含的源代码文件)。
static存储类型修饰符指定了变量具有文件作用域。
static int num;static void add(int);main(){scanf("%d",&num);add(num)printf("%d\n",num);}void add(num){num++;}上面的程序中变量num和函数add()在声明是采用了static存储类型修饰符,这使得它们具有文件作用域,仅爱定义它们的文件内可见。
由于我们提到的大多数程序都只有一个编译文件组成,所以这种写法没有实际意义。
但是实际工程上的文件有很多,它们不是由一个人写成的,由很多人共同完成,这些文件都是各自编译的,这难免使得某些人使用了一样的全局变量名,那么为了以后程序中各自的变量和函数不互相干扰,就可以使用static修饰符,这样在连接到同一个程序的其他代码文件而言就是不可见的。
二、变量存储类型前面我们说了,声明变量时用如下类似的形式:int num;float total;它们都没有存储类型修饰符,我们在声明时也可以通过存储类型修饰符来告诉编译器将要处理什么类型的变量。
存储类型有以下四种:自动(auto)、静态(static)、外部(extern)、寄存器(regiser)。
1.自动存储类型自动存储类型修饰符指定了一个局部变量为自动的,这意味着,每次执行到定义该变量的语句块时,都将会为该变量在内存中产生一个新的拷贝,并对其进行初始化。
实际上,如果不特别指明,局部变量的存储类型就默认为自动的,因此,加不加auto都可以。
main(){auto int num=5;printf("%d\n",num);}在这个例子中,不论变量num的声明是否包含关键字auto,代码的执行效果都是一样的。
函数的形式参数存储类型默认也是自动的。
2.静态存储变量前面已经使用了static关键字,但是对于局部变量,静态存储类型的意义是不一样的,这时,它是和自动存储类型相对而言的。
静态局部变量的作用域仍然近局限于声明它的语句块中,但是在语句块执行期间,变量将始终保持它的值。
而且,初始化值只在语句块第一次执行是起作用。
在随后的运行过程中,变量将保持语句块上一次执行时的值。
看下面两个对应的程序:/*1.C*/ /*2.C*/int add(); int add();main() main(){ {int result; int result;result=add() result=add();printf("%d ",result); printf("%d ",result);result=add(); result=add();printf("%d ",result); printf("%d ",result);result=add(); result=add();printf("%d",result); printf("%d",result);} }int add() int add(){ {int num=50; static int num=50;num++; num++;return num; return num;} }上面两个源文件,只有函数add()里的变量声明有所不同,一个是自动存储类型,一个是静态存储类型。