C语言学习课件 第6章
合集下载
《新编C语言程序设计教程》课件第6章
第 6章 循环结构程序设计
第 6章 循环结构程序设计
6.1 while语句 6.2 do-while语句 6.3 for语句 6.4 终止循环语句 6.5 多重循环 6.6 程序设计举例
第 6章 循环结构程序设计
6.1 while语句
格式: while (条件表达式)
其中,条件表达式描述进行循环的条件,语句描述要反复执行 的操作,称为循环体。
for(i=1;;i++) sum+=i
第 6章 循环结构程序设计
(4) 表达式3也可省略,分号也不能省,此时循环体中应有改 变循环条件的语句。例如:
for(i=1;i<=100;) {sum+=i;i++;}
(5) 当缺省表达式1、表达式2、表达式3中的一个、二个或全 部,或当采用逗号表达式时,可产生for语句的多种变化形式。
第 6章 循环结构程序设计
6.2 do-while语句
do–while语句是while语句的倒装形式。 格式:
do 语句 while (条件表达式)
功能:先执行循环,再计算条件表达式的值。当条件表达式的 值为真时,代表循环的条件成立,则继续执行循环。当条件表达 式的值为假,代表循环的条件不成立,则退出循环,执行循环的 下一条语句。
do–while语句反复执行循环,直到循环的条件不成立时为止。
第 6章 循环结构程序设计
说明:
(1) do–while语句是先执行,后判断。如果循环的条件一开始 就不成立,循环也将执行一次。
(2) 与while语句一样,循环体中同样必须有改变循环条件的语 句,否则循环将不能终止,形成无限循环。
(3) 循环体为多条语句时必须采用复合语句。 (4) 当循环条件为永真条件时,将变成无限循环。
第 6章 循环结构程序设计
6.1 while语句 6.2 do-while语句 6.3 for语句 6.4 终止循环语句 6.5 多重循环 6.6 程序设计举例
第 6章 循环结构程序设计
6.1 while语句
格式: while (条件表达式)
其中,条件表达式描述进行循环的条件,语句描述要反复执行 的操作,称为循环体。
for(i=1;;i++) sum+=i
第 6章 循环结构程序设计
(4) 表达式3也可省略,分号也不能省,此时循环体中应有改 变循环条件的语句。例如:
for(i=1;i<=100;) {sum+=i;i++;}
(5) 当缺省表达式1、表达式2、表达式3中的一个、二个或全 部,或当采用逗号表达式时,可产生for语句的多种变化形式。
第 6章 循环结构程序设计
6.2 do-while语句
do–while语句是while语句的倒装形式。 格式:
do 语句 while (条件表达式)
功能:先执行循环,再计算条件表达式的值。当条件表达式的 值为真时,代表循环的条件成立,则继续执行循环。当条件表达 式的值为假,代表循环的条件不成立,则退出循环,执行循环的 下一条语句。
do–while语句反复执行循环,直到循环的条件不成立时为止。
第 6章 循环结构程序设计
说明:
(1) do–while语句是先执行,后判断。如果循环的条件一开始 就不成立,循环也将执行一次。
(2) 与while语句一样,循环体中同样必须有改变循环条件的语 句,否则循环将不能终止,形成无限循环。
(3) 循环体为多条语句时必须采用复合语句。 (4) 当循环条件为永真条件时,将变成无限循环。
C语言讲义第六章
CHAPTER 6: Structures
Page6-26
struct key { char *word; int count; };
sizeof(struct key)
back
CHAPTER 6: Structures
Page6-27
6.4 Pointer to Structure
type *p;
结构体是一个或多个变量的集合体
Chapter6
Structures
CHAPTER 6: Structures
Page6-1
6.1 Basics of Structures
6.2 Structures and Functions 6.3 Arrays of Structures 6.4 Pointers to Structures 6.5 Self-referential Structures
CHAPTER 6: Structures
Page6-18
/* return 1 if p in r , 0 if not*/
int ptinrect(struct point p,struct rect r) { return p.x>=r.pt1.x && p.x<r.pt2.x && p.y>=r.pt1.y && p.y<r.pt2.y;
6.6 Table Lookup
6.7 Typedef
6.8 Unions
6.9 Bits-fields
CHAPTER 6: Structures
Page6-2
A
structure is a collection of one or
C语言程序设计课件第6章 类与对象
(4)构造函数可以重载,即一个类中可以定 义多个参数个数或参数类型不同的构造函数。
2021/7/13
18
【例6.5】 使用构造函数替代例6.3中SetTime() 成员函数,并在主函数中,使用构造函数设置 时间为15时19分56秒并显示该时间。 构造函数也可以重载。关于重载的概念将在第 7章详细介绍,这里先看一个例子。 【例6.6】 构造函数重载定义示例。
【2021例/7/163 .8】 构造函数的调用。
21
6.3.2 析构函数 1.析构函数的特点 当对象创建时,会自动调用构造函数进行初始 化。当对象撤消时,也会自动调用析构函数进 行一些清理工作,如释放分配给对象的内存空 间等。与构造函数类似的是:析构函数也与类 同名,但在名字前有一个“~”符号,析构函数 也具有公有属性,也没有返回类型和返回值, 但析构函数不带参数,不能重载,所以析构函 数只有一个。 【例6.9】 析构函数程序举例。
26
6.4 对象数组与对象指针 6.4.1 对象数组 对象数组是指数组的每一个元素都是相同类型对象的 数组,也就是说,若一个类有若干个对象,把这一系 列的对象用一个数组来表示。对象数组的元素是对象, 不仅具有数据成员,而且还有成员函数。
对象数组的定义和普通数组的定义类似,一般格式如 下: 类名 数组名[第一维大小][第二维数组大小] 其中,类名是指该数组元素属于该类的对象,方括号 内的数组大小给出了某一维元素的个数。一维对象数 组只有一对方括号,二维对象数组要有两个方括号对, 等等。
25
普通构造函数在建立对象时被调用,而复制构造函数
在用已有对象初始化一个新对象时被调用。复制构造
函数被调用通常发生在以下3种情况:
(1)程序中需要新建一个对象并用一个类的对象
2021/7/13
18
【例6.5】 使用构造函数替代例6.3中SetTime() 成员函数,并在主函数中,使用构造函数设置 时间为15时19分56秒并显示该时间。 构造函数也可以重载。关于重载的概念将在第 7章详细介绍,这里先看一个例子。 【例6.6】 构造函数重载定义示例。
【2021例/7/163 .8】 构造函数的调用。
21
6.3.2 析构函数 1.析构函数的特点 当对象创建时,会自动调用构造函数进行初始 化。当对象撤消时,也会自动调用析构函数进 行一些清理工作,如释放分配给对象的内存空 间等。与构造函数类似的是:析构函数也与类 同名,但在名字前有一个“~”符号,析构函数 也具有公有属性,也没有返回类型和返回值, 但析构函数不带参数,不能重载,所以析构函 数只有一个。 【例6.9】 析构函数程序举例。
26
6.4 对象数组与对象指针 6.4.1 对象数组 对象数组是指数组的每一个元素都是相同类型对象的 数组,也就是说,若一个类有若干个对象,把这一系 列的对象用一个数组来表示。对象数组的元素是对象, 不仅具有数据成员,而且还有成员函数。
对象数组的定义和普通数组的定义类似,一般格式如 下: 类名 数组名[第一维大小][第二维数组大小] 其中,类名是指该数组元素属于该类的对象,方括号 内的数组大小给出了某一维元素的个数。一维对象数 组只有一对方括号,二维对象数组要有两个方括号对, 等等。
25
普通构造函数在建立对象时被调用,而复制构造函数
在用已有对象初始化一个新对象时被调用。复制构造
函数被调用通常发生在以下3种情况:
(1)程序中需要新建一个对象并用一个类的对象
C语言课件第6章 数组
6.2.3 一维数组元素的初始化
一维数组初始化格式为: 数据类型 数组名[常量表达式]={初值表}; (1)在定义时对数组元素赋初值。 例如:int a[5]={1,2,3,4,5}; (2)“初值表”中的初值个数,可以少于元素个数,即允许只给 部分元素赋初值。例如:int a[5]={1,2,3}; (3)如果对数组的全部元素赋以初值,定义时可以不指定数组长 度(系统根据初值个数自动确定)。 int a[5]={1,2,3,4,5};可以写成: int a[ ]={1,2,3,4,5}; (4)如果想使一个数组中全部元素值为0,可以写成: int a[5]={0,0,0,0,0}; 或写成:int a[5]={0};
3.程序代码 #include "stdio.h" void main() /*定义50个浮点型变量分别保存每位同学的成绩*/ { float score1,score2,……,score50,average; scanf("%f",&score1); /*从键盘输入成绩*/ scanf("%f",&score2); …… scanf("%f",&score50); printf("pass-fail numbers:\n"); if(score1< 60) /*输出成绩不及格学生的学号*/ printf("1"); if(score2<60) printf("2"); …… if(score50<60) printf("50"); }
score[0] score[1] score[2] score[3] score[4] score[5] …… score[49]
C语言课件第6章
表达式3也可以省略, (3) 表达式3也可以省略,但此时程序设计者应另外设 法保证循环能正常结束。 法保证循环能正常结束。 for (i=1;i<=100;) { sum=sum+i; i++; } (4) 可以省略表达式 和表达式 ,只有表达式 ,即只给 可以省略表达式1和表达式 和表达式3,只有表达式2, 循环条件. 循环条件 for(;i<=100;) while(i<=100) {sum=sum+i; 相当于 { sum=sum+i; i++;} i++; }
第6 章 循 环 控 制
6.1 6.2 6.3 6.4 6.5 6.6 6.8
概述 goto语句以及用goto语句构成循环 语句以及用goto goto语句以及用goto语句构成循环 while语句 while语句 while语句 do while语句 for 语句 循环的嵌套 break语句和continue语句 语句和continue break语句和continue语句
回第六章
5、while循环执行的次数是 、 循环执行的次数是 1、do_while循环结束的条件是: 2、以下程序段,循环体执行几次? 循环结束的条件是: 、以下程序段,循环体 k=0; do { scanf(“%d”,&p); n++;} while(k=1) k++; while(p!=12345&&n<3);
表达式一般是关系表达式( i<=100)或逻辑表达式 (7) 表达式一般是关系表达式(如i<=100)或逻辑表达式 x<y),但也可以是数值表达式或字符表达式, (如a<b && x<y),但也可以是数值表达式或字符表达式, 只要其值为非零,就执行循环体。 只要其值为非零,就执行循环体。
C语言程序设计实用教程 第6章.ppt
for(i=0;i<N;i++)
if(score[i]>aver) n++;
printf(“average=%.2f \n ”,aver);
printf(“n=%d”,n);
}
6.1.2 数组中的相关概念
1.数组:是指一组具有相同类型的数据的有序的集合。
2.数组下标:是数组元素在数组中位置的一个索引或指示。
printf(“please input students grade:”);
for(i=0;i<N;i++)
score[i]是数组元素,用来存放第i个
{ scanf(“%f”,&score[i]); 学生成绩*
sum=sum+score[i]; /*将学生成绩累加到总分中 */
}
aver=sum/N;
则数组a中元素的初始值为系统分配给数组元素的内存单 元中的原始值,这些值对编程者来说是不可预知的,因此 在使用时要注意。
(2)若定义数组时在类型名前面加一个关键字static,即将 数组定义成静态存储,这时不为数组赋初值,系统也会自 动将全部元素赋以0值。例如: static int b[5]; 表示定义了一个静态数组b,该数组中所有元素值均为0。
aver=sum/100;
/*求出平均成绩*/
在本程序中能否统计高于平均分的学生人数呢?
用数组来解决这个问题,不仅效率高而且程序编写容易。
#define N 100 void main()
score[N]表示数组,用来存放 N个学生的成绩
{ int i,n=0;
float score[N],sum=0,aver;
一维数组的初始化有以下几种情形:
精品课件-数据结构-C语言描述-第6章
结点,结论成立。设当i=k时结论成立,即二叉树上至多有2k–1 个 结点, 则当i=k+1时,因为每个结点最多只有两个孩子,所以,第 k+1层上至多有2*2k –1 =2k个结点,性质成立。
第6章 树 性质2 高度为h的二叉树上至多有2h -1个结点。 当h=0时,二叉树为空二叉树。当h>0时,利用性质1,高度为h 的二叉树中结点的总数最多为
(6-2)
2h 1 - 1 < n≤2h - 1
移项得 (6-3)
2h 1 < n+1≤2h
取对数 (6-4)
h - 1 < lb(n+1)≤h
第6章 树
性质6 假定对一棵有n个结点的完全二叉树中的结点,按从 上到下、从左到右的顺序,从1到n编号(见图6-7),设树中某一 个结点的序号为i,1≤i≤n,则有以下关系成立:
第6章 树
图6-1描述了欧洲部分语言的谱系关系,它是一个后裔图, 图中使用的描述树形结构数据的形式为倒置的树形表示法。在前 几章中,我们学习了多种线性数据结构,但是一般来讲,这些数 据结构不适合表示如图6-1所示的层次结构的数据。为了表示这 类层次结构的数据,我们采用树形数据结构。在本章中我们将学 习多种不同特性的树形数据结构,如一般树、二叉树、穿线二叉 树、堆和哈夫曼树等。
第6章 树
Proto Indo-European 原始印欧语
Italic 古意大利语
… Latin 拉丁语
Hellenic 古希腊语
Greek 希腊语
…
Germanic 日尔曼语
North Germanic 北日尔曼语
…
West Germanic 西日尔曼语
Spanish French Italian 西班牙语 法语 意大利语
第6章 树 性质2 高度为h的二叉树上至多有2h -1个结点。 当h=0时,二叉树为空二叉树。当h>0时,利用性质1,高度为h 的二叉树中结点的总数最多为
(6-2)
2h 1 - 1 < n≤2h - 1
移项得 (6-3)
2h 1 < n+1≤2h
取对数 (6-4)
h - 1 < lb(n+1)≤h
第6章 树
性质6 假定对一棵有n个结点的完全二叉树中的结点,按从 上到下、从左到右的顺序,从1到n编号(见图6-7),设树中某一 个结点的序号为i,1≤i≤n,则有以下关系成立:
第6章 树
图6-1描述了欧洲部分语言的谱系关系,它是一个后裔图, 图中使用的描述树形结构数据的形式为倒置的树形表示法。在前 几章中,我们学习了多种线性数据结构,但是一般来讲,这些数 据结构不适合表示如图6-1所示的层次结构的数据。为了表示这 类层次结构的数据,我们采用树形数据结构。在本章中我们将学 习多种不同特性的树形数据结构,如一般树、二叉树、穿线二叉 树、堆和哈夫曼树等。
第6章 树
Proto Indo-European 原始印欧语
Italic 古意大利语
… Latin 拉丁语
Hellenic 古希腊语
Greek 希腊语
…
Germanic 日尔曼语
North Germanic 北日尔曼语
…
West Germanic 西日尔曼语
Spanish French Italian 西班牙语 法语 意大利语
《C语言程序设计》电子课件 第6章课件
}
运行结果:
Please input x: 7↙
Found 7,located in 6 position
>
Your site here
重
活动:技能考核
庆
电
子 工
▪判断分析题
程
职
业 学
➢语句“ int n=5,a[n]; ”是否正确?
院
➢若有“int b[5]={1,1,2,3,4};”,则b[5]的值
成:int a[]={1,2,3};
计 算
这样是无法达到数组长度为5的,此时该数组的实际
机 学
长度为3。
院
>
Your site here
重
6.1 一维数组
庆
电
子 工
6.1.2 一维数组的应用
程
职 业
▪通过有效常量下标使用数组元素
学 院
例:int a[8] = {0,1,2,3,4,5,6,7 } ;
算 机 学
的位置,就像水泡上浮似的,所以称为“起泡法”或“冒泡法 ”。
院
>
Your site here
6.1 一维数组
重 庆
6.1.2 一维数组的应用
电 子
▪冒泡法思想分析
工
程 职
例:b[6]={10,8,5,7,3,1}
业
学
院
计
算 机 学 院
第1轮共比较5次
>
Your site here
重 庆
{ t = 10-j; /*本轮要比较的次数*/
计
for (i = 0; i< t; i ++)
算
if (a[i] > a[i+1])
C语言程序设计课件第06章数组、指针与字符串.ppt
pa+i)就是a[i]. –a[i], *(pa+i), *(a+i), pa[i]都是等效的。 –不能写 a++,因为a是数组首地址(是常量)。
17
指针数组
指 数组的元素是指针类型 针 例:Point *pa[2];
由pa[0],pa[1]两个指针组成
*i_pointer 3i
2000
9
指针变量的初始化
指 语法形式 存储类型 数据类型 *指针名=初始地址; 例:int a , *pa=&a;
针 注意事项
➢用变量地址作为初值时,该变量必须在指针初始化 之前已说明过,且变量类型应与指针类型一致。
➢可以用一个已赋初值的指针去初始化另一个指针变 量。
组 ➢ 数组下标从零开始。 ➢ 下标必须是整形表达式。 ➢ 数组元素可以在定义时直接给出初始值列表。 ➢ 数组元素作函数参数同简单变量作函数参数。 ➢ 数组名作函数参数传递的是地址值。 ➢ 二维数组在内存中按行存放。
4
对象数组
数 声明:
类名 数组名[元素个数];
组 访问方法:
数组名[下标].成员名
与!=的关系运算。
针
– 指向不同数据类型的指针,以及指针与一
般整数变量之间的关系运算是无意义的。
– 指针可以和零之间进行等于或不等于的关
系运算。例如:p==0或p!=0
16
指向数组元素的指针
指 声明与赋值
例:int a[10], *pa;
针 pa=&a[0]; 或 pa=a;
通过指针引用数组元素
C++语言程序设计
第六章 数组、指针与字符串
本章主要内容
数组 指针 动态存储分配 深拷贝与浅拷贝 字符串
17
指针数组
指 数组的元素是指针类型 针 例:Point *pa[2];
由pa[0],pa[1]两个指针组成
*i_pointer 3i
2000
9
指针变量的初始化
指 语法形式 存储类型 数据类型 *指针名=初始地址; 例:int a , *pa=&a;
针 注意事项
➢用变量地址作为初值时,该变量必须在指针初始化 之前已说明过,且变量类型应与指针类型一致。
➢可以用一个已赋初值的指针去初始化另一个指针变 量。
组 ➢ 数组下标从零开始。 ➢ 下标必须是整形表达式。 ➢ 数组元素可以在定义时直接给出初始值列表。 ➢ 数组元素作函数参数同简单变量作函数参数。 ➢ 数组名作函数参数传递的是地址值。 ➢ 二维数组在内存中按行存放。
4
对象数组
数 声明:
类名 数组名[元素个数];
组 访问方法:
数组名[下标].成员名
与!=的关系运算。
针
– 指向不同数据类型的指针,以及指针与一
般整数变量之间的关系运算是无意义的。
– 指针可以和零之间进行等于或不等于的关
系运算。例如:p==0或p!=0
16
指向数组元素的指针
指 声明与赋值
例:int a[10], *pa;
针 pa=&a[0]; 或 pa=a;
通过指针引用数组元素
C++语言程序设计
第六章 数组、指针与字符串
本章主要内容
数组 指针 动态存储分配 深拷贝与浅拷贝 字符串
大学C语言实用教程(课件)-第6章-指针
int *p=&a;
// p指向a
printf("a=%p b=%p c=%p p=%p\n",&a,&b,&c,&p); printf("p=%p *p=%d\n",p,*p);
p--;
}
// p指向a前面的存储单元
printf("p=%p *p=%d\n",p,*p);
2. 指针与整数相加减 指针加减一个整数n可以使指针移动,可以访问新地址。
char c= 'A',*pc=&c; float a=3.0,*pa=&a;
指针变量指向变量示意图
pa FF74 FF70 FF71 FF72 FF73 FF74 a 3.0 FF75 FF76 FF77 FF78 pc FF7C FF79 FF7A FF7B c A FF7C
② 赋值方法 先定义指针,然后用赋值语句将所指变量的地址赋给它。例如 char c,*pc;
4. 两个同类型指针相减
x[0]
如果两个同类型指针之间所存储的数据的 x[2] 类型也与指针相同(通常是数组的情况),则相 减的结果是这两个指针之间所包含的数据个数。 x[3]
x[4]
x[1]
【例】两个同类型指针相减。 #include <stdio.h> void main() { float x[10]; float *p,*q; p=&x[2]; q=&x[8]; printf("q-p=%d\n",q-p); }
6.1.2 指针和指针变量
1.指针和指针变量的概念
变量的指针:该变量在内存中的地址。 指针变量:专门用来存放变量地址的特殊变量。 在不致引起混淆的情况下,把指针变量简称为指针。
c语言基础 ppt第6新章
20/51
函数的递归调用 例4 求n!
问题分析:计算n!的公式可写成如下形式
1 n 0,1 n! n *(n 1)! n 1
显然,这是一个递归形式的公式,在描述“阶乘”算法 时又用到了“阶乘”的概念。
递归结束的条件是n = 0或1。
21/51
函数的递归调用 例4 求n!
假
for j=0 to 6 输出结果
结 束
10/51
#include <stdio.h> #define N 7 void main() { int nCardArray[N]={13,8,6,1,2,3,4}; int t,i,j; for(i=0;i<N-1;i++) for(j=0;j<N-1-i;j++) if(nCardArray[j]>nCardArray[j+1]) { t=nCardArray[j]; nCardArray[j]=nCardArray[j+1]; nCardArray[j+1]=t; } for(i=0;i<N;i++) printf("%d ", nCardArray[i]); printf("\n"); 11/51 }
开 始 开 始 开 始
输入累加数 和指数
设定循环控制变量、初始 化、接收传入累加数和指数
设定循环控制变量、初始 化、接收传入底数和指数
调用Add(累加 数,指数)
for i=0 to 累加数
for i=0 to 指数
lSum+=Power (i, 指数) 输出结果
lPowerVal=lPowerVal*底数值
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
存储类别( 存储类别 ( storage class)确定了变量在 ) 内存中的存储方法; 内存中的存储方法; 存储的方式为两大类: 静态存储类和 存储的方式为两大类 : 静态存储类 和 动态 存储类; 存储类; 具体包括四种: 自动的( 具体包括四种 : 自动的 ( auto), 静态的 ) ( static), 寄存器的 ( register) 和 外部 ) 寄存器的( ) 的(extern)。 )
6.1存储类别 . 存储类别
2)静态局部变量(局部静态变量) )静态局部变量(局部静态变量) void fn() { int i = 3; static m; //… } //m被定义为静态局部变量 被定义为静态局部变量
6.1存储类别 . 存储类别
说明: 说明: 1. 静态局部变量的内存空间在全局 静态数据区; 静态局部变量的内存空间在全局\静态数据区; 静态数据区 2. 对静态局部变量 , 在编译时赋初值 , 且只赋一 对静态局部变量, 在编译时赋初值, 次; 3. 如对静态局部变量没有赋初值 , 则编译器自动 如对静态局部变量没有赋初值, 自动付初值0( 整数类型) 或空字符( 自动付初值 ( 整数类型 ) 或空字符 ( 字符类 型); 静态局部变量也只能由定义它的函数引用。 4. 静态局部变量也只能由定义它的函数引用。
6.2 作用域与可见性 .
例如// 例如 void fn(int x) //x的作用域从此开始 的作用域从此开始 { int y = 1; //y的作用域从此开始 的作用域从此开始 if (x<y) printf(“%d”, x); else printf(“%d”,y); } //x和y的作用域到此结束 和 的作用域到此结束
6.2 作用域与可见性 .
4 文件(全局)作用域 文件(全局) 文件作用域是作用在所有函数定义之外说 明的, 起作用域从说明点开始, 明的 , 起作用域从说明点开始 , 一直延伸 到源文件结束。 到源文件结束。 全局变量和函数具有文件作用域。 全局变量和函数具有文件作用域。
6.2 作用域与可见性 .
6.1存储类别 . 存储类别
静态全局变量的作用: 静态全局变量的作用:
1)不必担心另外源文件使用它的名字; )不必担心另外源文件使用它的名字; 2) 源文件的全局变量 ( 静态的 ) 不能被其他 ) 源文件的全局变量( 静态的) 源文件所用,不能被其他源文件所修改,保证 源文件所用,不能被其他源文件所修改, 变量的值是可靠的。 变量的值是可靠的。
6.3 生命期 .
6.3.2 局部生命期
在函数内部声明的变量或者是块中声明的变量(静态变量除外 具 在函数内部声明的变量或者是块中声明的变量 静态变量除外)具 静态变量除外 有局部生命期; 有局部生命期; 局部生命期开始于程序执行经过声明点时, 局部生命期开始于程序执行经过声明点时,而结束与其作用域结 束时; 束时; 具有局部生命期的变量具有局部作用域,但反之不然; 具有局部生命期的变量具有局部作用域,但反之不然; 具有局部生命期的变量驻存在内存的栈区; 具有局部生命期的变量驻存在内存的栈区; 具有局部生命期的变量如果未被初始化,则内容不可知。 具有局部生命期的变量如果未被初始化,则内容不可知。
6.2 作用域与可见性 .
6.2.1作用域 . . 作用域 作用域是标识符在程序中有效范围, 作用域是标识符在程序中有效范围 , 标识 符的引入与声明有关, 符的引入与声明有关 , 作用域开始于标识 符的声明处。 符的声明处。 标识符有四种作用域, 函数作用域、 标识符有四种作用域 , 即 函数作用域 、 文 全局) 作用域、 局部( 作用域和 件 ( 全局 ) 作用域 、 局部 ( 块 ) 作用域 和 函数原型作用域。 函数原型作用域。
6.2 作用域与可见性 .
例如// 例如 void fn() { for (int i = 0;i < 100; i ++) //i的作用域从此开始 ; 的作用域从此开始 { double f = 4.0; } } //i的作用域到此结束 的作用域到此结束
6.2 作用域与可见性 .
2 函数作用域 标号是唯一具有函数作用域的标识符。 标号是唯一具有函数作用域的标识符 。 标 号声明使得该标识符在一个函数内的任何 位置均可以被使用。 位置均可以被使用。
6.1存储类别 . 存储类别
//file1.c int a = 5; int b = 6; //file2.c int a; //error,重复定义 ,
extern double b; // error,类型不一致 , // error,无定义 ,
extern int c; extern int c;
6.1存储类别 . 存储类别
6.1.3 静态存储类别
1)静态全局变量(全局静态变量) )静态全局变量(全局静态变量) 在全局变量前加一个static, 在全局变量前加一个static,使该变量只 能在这个源文件中可用, 能在这个源文件中可用,称之为全局静态变量 静态全局变量) (静态全局变量)。 静态全局变量对组成程序的其它源文件是无效 的。 如果没有对静态全局变量初始化, 如果没有对静态全局变量初始化,则编译时自 动赋初值为零。 动赋初值为零。
6.1存储类别 . 存储类别
C语言中每一个变量和函数有两个属性: 语言中每一个变量和函数有两个属性: 语言中每一个变量和函数有两个属性 数据类型 存储类别 数据类型确定了变量: 数据类型确定了变量: (1)所占内存空间的大小 ) (2)表示数值的范围 ) (3)能够进行的操作 )
6.1存储类别 . 存储类别
6.1存储类别 . 存储类别
作用: 作用: 1. 需要保留函数上一次调用结束时的值 2. 如果初始化后 , 变量值只被引用而不改变其值 , 如果初始化后, 变量值只被引用而不改变其值, 则使用局部静态变量; 则使用局部静态变量; 3. 数组的初始化; 数组的初始化; 4. 可以记录函数调用的次数。 可以记录函数调用的次数。
6.1存储类别 . 存储类别
寄存器说明只使用于局部变量; 寄存器说明只使用于局部变量; 其作用是将使用频率较高的变量存储在寄存 器中; 器中; 编译器有可能会忽略register的声明; 的声明; 编译器有可能会忽略 的声明 目前的编译器能够识别频繁使用的变量, 目前的编译器能够识别频繁使用的变量 , 并 能够在不需要程序员作出register说明的情况 能够在不需要程序员作出 说明的情况 下把这些变量存放到寄存器中。 下把这些变量存放到寄存器中。
6.2 作用域与可见性 .
可以用符号::引用全局变量。 可以用符号::引用全局变量。 ::引用全局变量 例如: 例如:// int i = 3 { int i = 1; ::i = 4; }
6.3 生命期 .
生命期与存储区域密切相关, 生命期与存储区域密切相关 , 对应于 全局\静态数据区 堆区、 静态数据区、 全局 静态数据区 、 堆区 、 栈区的生命期分 别为静态生命期 动态生命期和 静态生命期、 别为 静态生命期 、 动态生命期 和 局部生命 期。
构成一个程序的多个源文件之间, 构成一个程序的多个源文件之间,通过声明数 据或函数为外部的( 据或函数为外部的(extern)来进行沟通; )来进行沟通; 默认的函数声明总是extern的。在连接时,连 的 在连接时, 默认的函数声明总是 接程序在组成该程序的源文件中搜索函数的定 义; 的变量说明是变量声明, 带extern的变量说明是变量声明,不是变量定 的变量说明是变量声明 义;
6.2 作用域与可见性 .
1 局部(块)作用域 局部( 当标识符的声明出现在由一对花括号所括 起来的一段程序( 内时, 起来的一段程序 ( 块 ) 内时 , 该标识符的 作用域从声明点开始, 到块结束处为止, 作用域从声明点开始 , 到块结束处为止 , 该作用域的范围具有局部性。 该作用域的范围具有局部性。
6.2.2 可见性 . . 可见性从另一角度表现标识符的有效性, 可见性从另一角度表现标识符的有效性 , 标识符在某个位置可见, 标识符在某个位置可见 , 表示该标识符可 以被引用; 以被引用; 可见性域作用域是一致的; 可见性域作用域是一致的; 作用域指的标识符的有效范围, 作用域指的标识符的有效范围 , 而可见性 是分析在某一位置标识符的有效性; 是分析在某一位置标识符的有效性;
6.3 生命期(生存期) . 生命期(生存期)
6.3.1 静态生命期
静态生命期与程序的运行期相同,只要程序一开始运行, 静态生命期与程序的运行期相同,只要程序一开始运行,这种生 命期的变量就存在,当程序结束时,其生命期就结束; 命期的变量就存在,当程序结束时,其生命期就结束; 变量在全局\静态数据区分配空间的,具有静态生命期; 变量在全局 静态数据区分配空间的,具有静态生命期; 静态数据区分配空间的 全局变量、静态全局变量、静态局部变量都具有静态生命期; 全局变量、静态全局变量、静态局部变量都具有静态生命期; 具有文件作用域的变量具有静态生命期; 具有文件作用域的变量具有静态生命期; 静态生命期的变量,若无显式初始化,则自动初始化为 。 静态生命期的变量,若无显式初始化,则自动初始化为0。
6.1存储类别 . 存储类别
3)静态函数(内部函数) )静态函数(内部函数) 在函数声明前加一个static,使该函数只 在函数声明前加一个 , 能在这个源文件中可用,称之为静态函数。 能在这个源文件中可用 , 称之为静态函数。 静态函数的作用: 静态函数的作用:
1. 它允许其它源文件建立并使用同名的函数, 它允许其它源文件建立并使用同名的函数 , 而不相互冲突; 而不相互冲突; 2. 声明为静态的函数不能被其它源文件调用, 声明为静态的函数不能被其它源文件调用 , 因为它的名字不能得到。 因为它的名字不能得到。
6.1存储类别 . 存储类别
6.1.1 自动存储类别 自动类型说明了一个自动变量。 自动类型说明了一个自动变量。 int f(auto int a) ( ) { auto int i = 1; //… } // // i存储类别 . 存储类别
6.1存储类别 . 存储类别
2)静态局部变量(局部静态变量) )静态局部变量(局部静态变量) void fn() { int i = 3; static m; //… } //m被定义为静态局部变量 被定义为静态局部变量
6.1存储类别 . 存储类别
说明: 说明: 1. 静态局部变量的内存空间在全局 静态数据区; 静态局部变量的内存空间在全局\静态数据区; 静态数据区 2. 对静态局部变量 , 在编译时赋初值 , 且只赋一 对静态局部变量, 在编译时赋初值, 次; 3. 如对静态局部变量没有赋初值 , 则编译器自动 如对静态局部变量没有赋初值, 自动付初值0( 整数类型) 或空字符( 自动付初值 ( 整数类型 ) 或空字符 ( 字符类 型); 静态局部变量也只能由定义它的函数引用。 4. 静态局部变量也只能由定义它的函数引用。
6.2 作用域与可见性 .
例如// 例如 void fn(int x) //x的作用域从此开始 的作用域从此开始 { int y = 1; //y的作用域从此开始 的作用域从此开始 if (x<y) printf(“%d”, x); else printf(“%d”,y); } //x和y的作用域到此结束 和 的作用域到此结束
6.2 作用域与可见性 .
4 文件(全局)作用域 文件(全局) 文件作用域是作用在所有函数定义之外说 明的, 起作用域从说明点开始, 明的 , 起作用域从说明点开始 , 一直延伸 到源文件结束。 到源文件结束。 全局变量和函数具有文件作用域。 全局变量和函数具有文件作用域。
6.2 作用域与可见性 .
6.1存储类别 . 存储类别
静态全局变量的作用: 静态全局变量的作用:
1)不必担心另外源文件使用它的名字; )不必担心另外源文件使用它的名字; 2) 源文件的全局变量 ( 静态的 ) 不能被其他 ) 源文件的全局变量( 静态的) 源文件所用,不能被其他源文件所修改,保证 源文件所用,不能被其他源文件所修改, 变量的值是可靠的。 变量的值是可靠的。
6.3 生命期 .
6.3.2 局部生命期
在函数内部声明的变量或者是块中声明的变量(静态变量除外 具 在函数内部声明的变量或者是块中声明的变量 静态变量除外)具 静态变量除外 有局部生命期; 有局部生命期; 局部生命期开始于程序执行经过声明点时, 局部生命期开始于程序执行经过声明点时,而结束与其作用域结 束时; 束时; 具有局部生命期的变量具有局部作用域,但反之不然; 具有局部生命期的变量具有局部作用域,但反之不然; 具有局部生命期的变量驻存在内存的栈区; 具有局部生命期的变量驻存在内存的栈区; 具有局部生命期的变量如果未被初始化,则内容不可知。 具有局部生命期的变量如果未被初始化,则内容不可知。
6.2 作用域与可见性 .
6.2.1作用域 . . 作用域 作用域是标识符在程序中有效范围, 作用域是标识符在程序中有效范围 , 标识 符的引入与声明有关, 符的引入与声明有关 , 作用域开始于标识 符的声明处。 符的声明处。 标识符有四种作用域, 函数作用域、 标识符有四种作用域 , 即 函数作用域 、 文 全局) 作用域、 局部( 作用域和 件 ( 全局 ) 作用域 、 局部 ( 块 ) 作用域 和 函数原型作用域。 函数原型作用域。
6.2 作用域与可见性 .
例如// 例如 void fn() { for (int i = 0;i < 100; i ++) //i的作用域从此开始 ; 的作用域从此开始 { double f = 4.0; } } //i的作用域到此结束 的作用域到此结束
6.2 作用域与可见性 .
2 函数作用域 标号是唯一具有函数作用域的标识符。 标号是唯一具有函数作用域的标识符 。 标 号声明使得该标识符在一个函数内的任何 位置均可以被使用。 位置均可以被使用。
6.1存储类别 . 存储类别
//file1.c int a = 5; int b = 6; //file2.c int a; //error,重复定义 ,
extern double b; // error,类型不一致 , // error,无定义 ,
extern int c; extern int c;
6.1存储类别 . 存储类别
6.1.3 静态存储类别
1)静态全局变量(全局静态变量) )静态全局变量(全局静态变量) 在全局变量前加一个static, 在全局变量前加一个static,使该变量只 能在这个源文件中可用, 能在这个源文件中可用,称之为全局静态变量 静态全局变量) (静态全局变量)。 静态全局变量对组成程序的其它源文件是无效 的。 如果没有对静态全局变量初始化, 如果没有对静态全局变量初始化,则编译时自 动赋初值为零。 动赋初值为零。
6.1存储类别 . 存储类别
C语言中每一个变量和函数有两个属性: 语言中每一个变量和函数有两个属性: 语言中每一个变量和函数有两个属性 数据类型 存储类别 数据类型确定了变量: 数据类型确定了变量: (1)所占内存空间的大小 ) (2)表示数值的范围 ) (3)能够进行的操作 )
6.1存储类别 . 存储类别
6.1存储类别 . 存储类别
作用: 作用: 1. 需要保留函数上一次调用结束时的值 2. 如果初始化后 , 变量值只被引用而不改变其值 , 如果初始化后, 变量值只被引用而不改变其值, 则使用局部静态变量; 则使用局部静态变量; 3. 数组的初始化; 数组的初始化; 4. 可以记录函数调用的次数。 可以记录函数调用的次数。
6.1存储类别 . 存储类别
寄存器说明只使用于局部变量; 寄存器说明只使用于局部变量; 其作用是将使用频率较高的变量存储在寄存 器中; 器中; 编译器有可能会忽略register的声明; 的声明; 编译器有可能会忽略 的声明 目前的编译器能够识别频繁使用的变量, 目前的编译器能够识别频繁使用的变量 , 并 能够在不需要程序员作出register说明的情况 能够在不需要程序员作出 说明的情况 下把这些变量存放到寄存器中。 下把这些变量存放到寄存器中。
6.2 作用域与可见性 .
可以用符号::引用全局变量。 可以用符号::引用全局变量。 ::引用全局变量 例如: 例如:// int i = 3 { int i = 1; ::i = 4; }
6.3 生命期 .
生命期与存储区域密切相关, 生命期与存储区域密切相关 , 对应于 全局\静态数据区 堆区、 静态数据区、 全局 静态数据区 、 堆区 、 栈区的生命期分 别为静态生命期 动态生命期和 静态生命期、 别为 静态生命期 、 动态生命期 和 局部生命 期。
构成一个程序的多个源文件之间, 构成一个程序的多个源文件之间,通过声明数 据或函数为外部的( 据或函数为外部的(extern)来进行沟通; )来进行沟通; 默认的函数声明总是extern的。在连接时,连 的 在连接时, 默认的函数声明总是 接程序在组成该程序的源文件中搜索函数的定 义; 的变量说明是变量声明, 带extern的变量说明是变量声明,不是变量定 的变量说明是变量声明 义;
6.2 作用域与可见性 .
1 局部(块)作用域 局部( 当标识符的声明出现在由一对花括号所括 起来的一段程序( 内时, 起来的一段程序 ( 块 ) 内时 , 该标识符的 作用域从声明点开始, 到块结束处为止, 作用域从声明点开始 , 到块结束处为止 , 该作用域的范围具有局部性。 该作用域的范围具有局部性。
6.2.2 可见性 . . 可见性从另一角度表现标识符的有效性, 可见性从另一角度表现标识符的有效性 , 标识符在某个位置可见, 标识符在某个位置可见 , 表示该标识符可 以被引用; 以被引用; 可见性域作用域是一致的; 可见性域作用域是一致的; 作用域指的标识符的有效范围, 作用域指的标识符的有效范围 , 而可见性 是分析在某一位置标识符的有效性; 是分析在某一位置标识符的有效性;
6.3 生命期(生存期) . 生命期(生存期)
6.3.1 静态生命期
静态生命期与程序的运行期相同,只要程序一开始运行, 静态生命期与程序的运行期相同,只要程序一开始运行,这种生 命期的变量就存在,当程序结束时,其生命期就结束; 命期的变量就存在,当程序结束时,其生命期就结束; 变量在全局\静态数据区分配空间的,具有静态生命期; 变量在全局 静态数据区分配空间的,具有静态生命期; 静态数据区分配空间的 全局变量、静态全局变量、静态局部变量都具有静态生命期; 全局变量、静态全局变量、静态局部变量都具有静态生命期; 具有文件作用域的变量具有静态生命期; 具有文件作用域的变量具有静态生命期; 静态生命期的变量,若无显式初始化,则自动初始化为 。 静态生命期的变量,若无显式初始化,则自动初始化为0。
6.1存储类别 . 存储类别
3)静态函数(内部函数) )静态函数(内部函数) 在函数声明前加一个static,使该函数只 在函数声明前加一个 , 能在这个源文件中可用,称之为静态函数。 能在这个源文件中可用 , 称之为静态函数。 静态函数的作用: 静态函数的作用:
1. 它允许其它源文件建立并使用同名的函数, 它允许其它源文件建立并使用同名的函数 , 而不相互冲突; 而不相互冲突; 2. 声明为静态的函数不能被其它源文件调用, 声明为静态的函数不能被其它源文件调用 , 因为它的名字不能得到。 因为它的名字不能得到。
6.1存储类别 . 存储类别
6.1.1 自动存储类别 自动类型说明了一个自动变量。 自动类型说明了一个自动变量。 int f(auto int a) ( ) { auto int i = 1; //… } // // i存储类别 . 存储类别