C Programing
2019-06-21 22:32:22 0 举报
AI智能生成
C Programing
作者其他创作
大纲/内容
C语言概述
语言特定
结构化语言
层次清晰
便于模块化方式组织程序
易于调试和维护
表现能力和处理能力强
有丰富的运算符和数据类型
可以直接访问内存的物理地址,进行bit一级的操作
实现了对硬件编程操作
可以用于系统软件的开发
应用软件的开发
效率高
可移植性强
C源程序的结构特点
一个C语言源程序可以由一个或多个源文件组成
每个源文件可由一个或多个函数组成
一个源程序不论由多少个文件组成,都有一个且只能有一个main函数,即主函数
源程序中可以有预处理命令(include 命令仅为其中的一种),预处理命令通常应放在源文件或源程序的最前面
每一个说明,每一个语句都必须以分号结尾。但预处理命令,函数头和花括号“}”之后不能加分号
标识符,关键字之间必须至少加一个空格以示间隔。若已有明显的间隔符,也可不再加空格来间隔
书写程序时应遵循的规则
一个说明或一个语句占一行
用{} 括起来的部分,通常表示了程序的某一层次结构。{}一般与该结构语句的第一个字母对齐,并单独占一行
低一层次的语句或说明可比高一层次的语句或说明缩进若干格后书写。
以便看起来更加清晰,增加程序的可读性。在编程时应力求遵循这些规则,以养成良好的编程风格
以便看起来更加清晰,增加程序的可读性。在编程时应力求遵循这些规则,以养成良好的编程风格
C语言的字符集
字母 小写字母a~z共26个,大写字母A~Z共26个
数字 0~9共10个
空白符 空格符、制表符、换行符等统称为空白符
标点和特殊字符
C语言词汇
标识符<br>
关键字
类型说明符
int, double
语句定义符
if else
预处理命令字
include
运算符
分隔符
逗号
逗号主要用在类型说明和函数参数表中,分隔各个变量
空格
空格多用于语句各单词之间,作间隔符。
在关键字,标识符之间必须要有一个以上的空格符作间隔, 否则将会出现语法错误
在关键字,标识符之间必须要有一个以上的空格符作间隔, 否则将会出现语法错误
常量
注释符
多行 /* */<br>
单行 //
数据类型、运算符、表达式
变量的说明
数据类型
储存类型
作用域
数据类型
基本数据类型
整型量
整型常量
整型变量
int
2bytes
short int
2bytes
long int || long
4bytes
unsigned int || unsigned
2bytes
实型量(浮点型)
实型常量
实型变量
float
占4个bytes,只能提供7位有效数字
double
占8个bytes,可提供16位有效数字
字符型量
字符常量
字符常量是用单引号括起来的一个字符
特点
字符常量只能用单引号括起来,不能用双引号或其它括号
字符常量只能是单个字符,不能是字符串
字符可以是字符集中任意字符。但数字被定义为字符型之后就<br>不能参与数值运算
字符变量
char
字符变量的取值是字符常量,即单个字符
转义字符
\n<br>
回车换行
\t
横向跳到下一制表位置<br>
\v
竖向跳格
\b
退格
\r
回车
\f
走纸换页
\\
反斜线符"\"<br>
\'
单引号符<br>
\a
鸣铃
字符串常量
定义
字符串常量是由一对双引号括起的字符序列
与字符常量的区别
字符常量由单引号括起来,字符串常量由双引号括起来
字符常量只能是单个字符,字符串常量则可以含一个或多个字符
可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。
在C语言中没有相应的字符串变量,但是可以用一个字符数组来存放一个字符串常量。
在C语言中没有相应的字符串变量,但是可以用一个字符数组来存放一个字符串常量。
符号常量
在C语言中,可以用一个标识符来表示一个常量,称之为符号常量
符号常量在使用之前必须先定义
#define 标识符 常量
构造数据类型
数组类型
结构类型
联合类型
指针类型
空类型
变量的初值和类型转换
变量初始化
在定义时给变量赋以初值
类型说明符 变量1=值1, 变量2=值2, ......
变量类型转换<br>
自动转换
定义
自动转换发生在不同数据类型的量混合运算时,由编译系统自动完成
遵循规则
若参与运算量的类型不同,则先转换成同一类型,然后进行运算
转换按数据长度增加的方向进行,以保证精度不降低
所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,
也要先转换成double型,再作运算
也要先转换成double型,再作运算
char型和short型参与运算时,必须先转换成int型
在赋值运算中,赋值号两边量的数据类型不同时, 赋值号右边量的类型将转换为左边量的类型。
如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度, 丢失的部分按四舍五入向前舍入
如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度, 丢失的部分按四舍五入向前舍入
强制转换
定义
强制类型转换是通过类型转换运算来实现的
一般形式
(类型说明符) (表达式)
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型
注意
类型说明符和表达式都必须加括号(单个变量可以不加括号),
如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了
如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了
无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,
而不改变数据说明时对该变量定义的类型
而不改变数据说明时对该变量定义的类型
运算符&表达式
运算符
算术运算符
符号
+ - * /
% 求余
++ 自增
++i
i自增1后再参与其它运算
i++
i参与运算后,i的值再自增1
-- 自减
--i
i自减1后再参与其它运算
i--
i参与运算后,i的值再自减1
算术表达式
是由算术运算符和括号连接起来的式子
关系运算符
> <
>= <=
== !=
逻辑运算符
&&
||
!
位操作运算符
&
位与
|
位或
~
位非
^
位异或
<<
左移
>>
右移
赋值运算符
运算符
简单赋值
=
复合算术赋值
+=
-=
*=
/=
%=
复合位运算赋值
&=
|=
^=
>>=
<<=
赋值表达式
由“= ”连接的式子称为赋值表达式。其一般形式为: 变量=表达式
赋值时的自动类型转换
实型赋予整型,舍去小数部分
整型赋予实型,数值不变,但将以浮点形式存放, 即增加小数部分(小数部分的值为0)。
字符型赋予整型,由于字符型为一个字节, 而整型为二个字节,
故将字符的ASCII码值放到整型量的低八位中,高八位为0
故将字符的ASCII码值放到整型量的低八位中,高八位为0
整型赋予字符型,只把低八位赋予字符量
复合赋值表达式
在赋值符“=”之前加上其它二目运算符可构成复合赋值符
exp: +=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=
一般形式
变量 双目运算符=表达式 它等效于 变量=变量 运算符 表达式
exp: a += 5
exp: a = a + 5
条件运算符
一个三目运算符
? :
逗号运算符
,
用于把若干表达式组合成一个表达式
一般形式
表达式1,表达式2
求值过程是分别求两个表达式的值,并以表达式2的值作为整个逗号表达式的值
说明点
逗号表达式一般形式中的表达式1和表达式2 也可以又是逗号表达式。例如: 表达式1,(表达式2,表达式3) 形成了嵌套情形。
因此可以把逗号表达式扩展为以下形式: 表达式1,表达式2,…表达式n 整个逗号表达式的值等于表达式n的值
因此可以把逗号表达式扩展为以下形式: 表达式1,表达式2,…表达式n 整个逗号表达式的值等于表达式n的值
程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值
并不是在所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中逗号只是用作各变量之间的间隔符
指针运算符
*<br>
取内容
&
取地址
求字节数运算符
sizeof
用于计算数据类型所占的字节数
特殊运算符
()
括号
[]
下标
优先级和结合性
结合性
左结合性
exp:算术运算符
右结合性
exp:赋值运算
优先级
C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。
在表达式中,优先级较高的先于优先级较低的进行运算
在表达式中,优先级较高的先于优先级较低的进行运算
表达式
C语言规定, 任何表达式在其未尾加上分号就构成为语句
C语言程序设计初步
C程序的语句
表达式语句
表达式语句由表达式加上分号“;”组成
一般形式
表达式;
典型
赋值语句
是由赋值表达式再加上分号构成的表达式语句
一般形式
变量=表达式;
注意点
由于在赋值符“=”右边的表达式也可以又是一个赋值表达式,因此,
下述形式 变量=(变量=表达式); 是成立的,从而形成嵌套的情形。
其展开之后的一般形式为: 变量=变量=…=表达式;
下述形式 变量=(变量=表达式); 是成立的,从而形成嵌套的情形。
其展开之后的一般形式为: 变量=变量=…=表达式;
在变量说明中给变量赋初值和赋值语句的区别。给变量赋初值是变量说明的一部分,
赋初值后的变量与其后的其它同类变量之间仍必须用逗号间隔,而赋值语句则必须用分号结尾
赋初值后的变量与其后的其它同类变量之间仍必须用逗号间隔,而赋值语句则必须用分号结尾
在变量说明中,不允许连续给多个变量赋初值。 如下述说明是错误的:<br> int a=b=c=5 必须写为 int a=5,b=5,c=5; 而赋值语句允许连续赋值
注意赋值表达式和赋值语句的区别。赋值表达式是一种表达式,
它可以出现在任何允许表达式出现的地方,而赋值语句则不能
它可以出现在任何允许表达式出现的地方,而赋值语句则不能
函数调用语句
由函数名、实际参数加上分号“;”组成
一般形式
函数名(实际参数表);
典型
数据输出语句
格式输出函数
printf函数
printf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中
调用一般形式
printf(“格式控制字符串”,输出表列)
格式控制字符串用于指定输出格式
格式字符串是以%开头的字符串,在%后面跟有各种格式字符,
以说明输出数据的类型、形式、长度、小数位数等
以说明输出数据的类型、形式、长度、小数位数等
格式字符串
一般形式
%[标志][输出最小宽度][.精度][长度]类型
其中方括号[]中的项为可选项
各项意义
类型
d
以十进制形式输出带符号整数(正数不输出负号)
o
以八进制形式输出无符号整数(不输出前缀O)
x
以十六进制形式输出无符号整数(不输出前缀OX)
u
以十进制形式输出无符号整数
f
以小数形式输出单、双精度实数
e
以指数形式输出单、双精度实数
g
以%f%e中较短的输出宽度输出单、双精度实数
c
输出单个字符
s
输出字符串
标志
-
结果左对齐,右边填空格
+
输出符号(正号或负号)空格输出值为正时冠以空格,为负时冠以负号
#
对c,s,d,u类无影响;对o类, 在输出时加前缀; 对x类,在输出时加前缀0x;
对e,g,f 类当结果有小数时才给出小数点
对e,g,f 类当结果有小数时才给出小数点
输出最小宽度
用十进制整数来表示输出的最少位数。 若实际位数多于定义的宽度,
则按实际位数输出, 若实际位数少于定义的宽度则补以空格或0
则按实际位数输出, 若实际位数少于定义的宽度则补以空格或0
精度
精度格式符以“.”开头,后跟十进制整数。本项的意义是:如果输出数字,则表示小数的位数;
如果输出的是字符, 则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分
如果输出的是字符, 则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分
长度
h
h表示按短整型量输出
l
l表示按长整型量输出
字符输出函数
putchar
putchar 函数是字符输出函数, 其功能是在显示器上输出单个字符
一般形式
putchar(字符变量)
数据输入语句
格式输入函数
scanf
scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中
一般形式
scanf(“格式控制字符串”,地址表列)
格式控制字符串的作用与printf函数相同,但不能显示非格式字符串,也就是不能显示提示字符串
址是由地址运算符“&”后跟变量名组成的
格式字符串
一般形式
%[*][输入数据宽度][长度]类型
其中有方括号[]的项为任选项
各项意义
类型
d
输入十进制整数
o
输入八进制整数
x
输入十六进制整数
u
输入无符号十进制整数
f或e
输入实型数(用小数形式或指数形式)
c
输入单个字符
s
输入字符串
“*”符
用以表示该输入项读入后不赋予相应的变量,即跳过该输入值
宽度
用十进制整数指定输入的宽度(即字符数)
长度<br>
l
l表示输入长整型数据(如%ld) 和双精度浮点数(如%lf)
h
h表示输入短整型数据
注意点
scanf函数中没有精度控制,如: scanf("%5.2f",&a); 是非法的。
不能企图用此语句输入小数为2位的实数
不能企图用此语句输入小数为2位的实数
scanf中要求给出变量地址,如给出变量名则会出错。如 scanf("%d",a);是非法的,
应改为scnaf("%d",&a);才是合法的
应改为scnaf("%d",&a);才是合法的
在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,
TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,
A即为非法数据)时即认为该数据结束
TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,
A即为非法数据)时即认为该数据结束
在输入字符数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符
键盘输入函数
getchar
getchar函数getchar函数的功能是从键盘上输入一个字符
一般形式
getchar()
通常把输入的字符赋予一个字符变量,构成赋值语句
exp:
char c;
c = getchar();
char c;
c = getchar();
注意点
getchar函数只能接受单个字符,输入数字也按字符处理。输入多于一个字符时,只接收第一个字符
使用本函数前必须包含文件“stdio.h”
在TC屏幕下运行含本函数程序时,将退出TC 屏幕进入用户屏幕等待用户输入。输入完毕再返回TC屏幕
控制语句
条件判断
if语句
switch语句
循环执行
do while语句
while语句
for语句
转向语句
break语句
goto语句
continue语句
return语句
复合语句
把多个语句用括号{}括起来组成的一个语句称复合语句
在程序中应把复合语句看成是单条语句,而不是多条语句
复合语句内的各条语句都必须以分号“;”结尾,在括号“}”外不能加分号
空语句
只有分号“;”组成的语句称为空语句
在程序中空语句可用来作空循环体
while(getchar()!='\n'); 本语句的功能是,只要从键盘输入的字符不是回车则重新输入。
这里的循环体为空语句
这里的循环体为空语句
C程序的基本结构
顺序结构
分支结构
关系运算符和表达式
概述
关系运算符都是双目运算符,其结合性均为左结合
优先级
算术运算符 --> 关系运算符 --> 逻辑运算符 --> 赋值运算符
表达式
表达式 关系运算符 表达式
exp: a + b > c - d
关系表达式的值是“真”和“假”,用“1”和“0”表示
逻辑运算符和表达式
概述
&& 和 || 为双目运算符, 具有左结合性
! 为单目运算符, 具有右结合性
优先级
()--> ! --> && --> ||
表达式
表达式 逻辑运算符 表达式
exp: i<j && x < y
逻辑运算的值也为“真”和“假”两种,用“1”和“0 ”来表示
求值规则
与运算&&参与运算的两个量都为真时,结果才为真,否则为假
或运算||参与运算的两个量只要有一个为真,结果就为真
非运算!参与运算量为真时,结果为假;参与运算量为假时,结果为真
if 语句
概述
用if语句可以构成分支结构。它根据给定的条件进行判断, 以决定执行某个分支程序段
三种基本形式
if(表达式) 语句;
如果表达式的值为真,则执行其后的语句, 否则不执行该语句
exp:
if (max<b) max=b;
if (max<b) max=b;
if (表达式)
语句1;
else
语句2;
语句1;
else
语句2;
如果表达式的值为真,则执行语句1,否则执行语句2
if(表达式1)
语句1;
else if(表达式2)
语句2;
...
else if(表达式m)
语句m;
else
语句n;
语句1;
else if(表达式2)
语句2;
...
else if(表达式m)
语句m;
else
语句n;
if语句的嵌套
在嵌套内的if语句可能又是if-else型的,这将会出现多个if和多个else重叠的情况,
这时要特别注意if和else的配对问题
这时要特别注意if和else的配对问题
C语言规定,else总是与它前面最近的if配对
注意
在三种形式的if语句中,在if关键字之后均为表达式。 该表达式通常是逻辑表达式或关系表达式,
但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量
但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量
在if语句中,条件判断表达式必须用括号括起来, 在语句之后必须加分号
在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,
则必须把这一组语句用{} 括起来组成一个复合语句。但要注意的是在}之后不能再加分号
则必须把这一组语句用{} 括起来组成一个复合语句。但要注意的是在}之后不能再加分号
条件运算符和条件表达式
如果在条件语句中,只执行单个的赋值语句时, 常可使用条件表达式来实现。
不但使程序简洁,也提高了运行效率。
不但使程序简洁,也提高了运行效率。
条件运算符为?和:
它是一个三目运算符,即有三个参与运算的量
一般形式
表达式1 ? 表达式2: 表达式3
求值规则
如果表达式1的值为真,则以表达式2 的值作为条件表达式的值,
否则以表达式3的值作为整个条件表达式的值。
否则以表达式3的值作为整个条件表达式的值。
switch语句
一般形式
switch(表达式){
case常量表达式1: 语句1;
case常量表达式2: 语句2;
…
case常量表达式n: 语句n;
default : 语句n+1;
}
case常量表达式1: 语句1;
case常量表达式2: 语句2;
…
case常量表达式n: 语句n;
default : 语句n+1;
}
注意
在case后的各常量表达式的值不能相同,否则会出现错误
在case后,允许有多个语句,可以不用{}括起来
各case和default子句的先后顺序可以变动,而不会影响程序执行结果
default子句可以省略不用
循环结构
while语句
一般形式
while(表达式) 语句;
语义
其中表达式是循环条件,语句为循环体
while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体语句
注意
while语句中的表达式一般是关系表达或逻辑表达式,只要表达式的值为真(非0)即可继续循环
循环体如包括有一个以上的语句,则必须用{}括起来, 组成复合语句
while(表达式)
{复合语句}
{复合语句}
应注意循环条件的选择以避免死循环
do while语句<br>
一般形式
do
语句;
while(表达式);
语句;
while(表达式);
语义
其中语句是循环体,表达式是循环条件
先执行循环体语句一次, 再判别表达式的值,若为真(非0)则继续循环,否则终止循环
与while语句的区别
do-while语句和while语句的区别在于do-while是先执行后判断,do-while至少要执行一次循环体
而while是先判断后执行,如果条件不满足,则一次循环体语句也不执行
注意
在if语句,while语句中, 表达式后面都不能加分号, 而在 do-while语句的表达式后面则必须加分号
do-while语句也可以组成多重循环,而且也可以和while语句相互嵌套
在do和while之间的循环体由多个语句组成时,也必须用{}括起来组成一个复合语句
do
{复合语句}
while(表达式);
{复合语句}
while(表达式);
do-while和while语句相互替换时,要注意修改循环控制条件
for语句
一般形式
for(表达式1;表达式2;表达3)
语句;
语句;
语义
各项表达式
表达式1 通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式
表达式2 通常是循环条件,一般为关系表达式或逻辑表达式
表达式3 通常可用来修改循环变量的值,一般是赋值语句
执行步骤
首先计算表达式1的值
再计算表达式2的值,若值为真(非0)则执行循环体一次, 否则跳出循环
然后再计算表达式3的值,转回第2步重复执行。
在整个for循环过程中,表达式1只计算一次,表达式2和表达式3则可能计算多次。
循环体可能多次执行,也可能一次都不执行
在整个for循环过程中,表达式1只计算一次,表达式2和表达式3则可能计算多次。
循环体可能多次执行,也可能一次都不执行
注意
for语句中的各表达式都可省略,但分号间隔符不能少
如:for(;表达式;表达式)省去了表达式1。for(表达式;;表达式)省去了表达式2。
for(表达式;表达式;)省去了表达式3。for(;;)省去了全部表达式
for(表达式;表达式;)省去了表达式3。for(;;)省去了全部表达式
在循环变量已赋初值时,可省去表达式1
如省去表达式2或表达式3则将造成无限循环, 这时应在循环体内设法结束循环
如省去表达式2或表达式3则将造成无限循环, 这时应在循环体内设法结束循环
循环体可以是空语句
for(int n=0 ; getchar() != '\n'; n++) ;
for语句也可与while,do-while语句相互嵌套,构成多重循环
转移语句
goto语句
一般形式
goto 语句标号;
其中语句标号是按标识符规定书写的符号, 放在某一语句行的
前面,标号后加冒号(:)
前面,标号后加冒号(:)
语句标号起标识语句的作用,与goto 语句配合使用。
如:
label: i++;
loop: while(x<7);
如:
label: i++;
loop: while(x<7);
语义
goto语句的语义是改变程序流向, 转去执行语句标号所标识的语句
使用
goto语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能
break语句
一般形式
break;
语义
break语句只能用在switch 语句或循环语句中,
其作用是跳出switch语句或跳出本层循环,转去执行后面的程序
其作用是跳出switch语句或跳出本层循环,转去执行后面的程序
由于break语句的转移方向是明确的,所以不需要语句标号与之配合
使用
使用break语句可以使循环语句有多个出口,在一些场合下使编程更加灵活、方便
continue语句
一般形式
continue;
语义
结束本次循环,即不再执行循环体中continue 语句之后的语句,
转入下一次循环条件的判断与执行
转入下一次循环条件的判断与执行
使用
本语句只结束本层本次的循环,并不跳出循环
数组
定义
具有相同类型的若干变量按有序的形式组织起来。
这些按序排列的同类数据元素的集合称为数组
这些按序排列的同类数据元素的集合称为数组
一个数组可以分解为多个数组元素,
这些数组元素可以是基本数据类型或是构造类型
这些数组元素可以是基本数据类型或是构造类型
一维数组
声明的一般形式
类型说明符 数组名 [常量表达式],……;
exp:float a[10], b[30];
类型说明符是任一种基本数据类型或构造数据类型
数组名是用户定义的数组标识符
方括号中的常量表达式表示数据元素的个数,也称为数组的长度
一维数组元素表示法
数组元素定义
数组元素是组成数组的基本单元
数组元素也是一种变量, 其标识方法为数组名后跟一个下标
下标表示了元素在数组中的顺序号
数组元素表示的一般形式
数组名[下标]
a[5], a[i+j], a[i++]
其中的下标只能为整型常量或整型表达式
必须先定义数组, 才能使用下标变量(数组元素)
在C语言中只能逐个地使用下标变量, 而不能一次引用整个数组
数组赋值及初始化
赋值语句对数组逐个赋值
初始化赋值(数组声明时赋值)
一般形式
static 类型说明符 数组名[常量表达式]={值,值……值};
其中static表示是静态存储类型, C语言规定只有静态存储数组和外部存储数组才可作初始化赋值
在{ }中的各数据值即为各元素的初值, 各值之间用逗号间隔
规定
可以只给部分元素赋初值。当{ }中值的个数少于元素个数时,只给前面部分元素赋值
static int a[10]={0,1,2,3,4};
表示只给a[0]~a[4]5个元素赋值,而后5个元素自动赋0值
只能给元素逐个赋值,不能给数组整体赋值
static int a[10]={1,1,1,1,1,1,1,1,1,1};
如不给可初始化的数组赋初值,则全部元素均为0值
如给全部元素赋值,则在数组说明中, 可以不给出数组元素的个数
static int a[5]={1,2,3,4,5};
static int a[]={1,2,3,4,5};
动态赋值可以在程序执行过程中,对数组作动态赋值。 这时可用循环语句配合scanf函数逐个对数组元素赋值
动态赋值
注意
数组的类型实际上是指数组元素的取值类型。
对于同一个数组,其所有元素的数据类型都是相同的
对于同一个数组,其所有元素的数据类型都是相同的
数组名的书写规则应符合标识符的书写规定
数组名不能与其它变量名相同
方括号中常量表达式表示数组元素的个数,如a[5]表示数组a有5个元素。
但是其下标从0开始计算。因此5个元素分别为a[0],a[1],a[2],a[3],a[4]。
但是其下标从0开始计算。因此5个元素分别为a[0],a[1],a[2],a[3],a[4]。
不能在方括号中用变量来表示元素的个数, 但是可以是符号常数或常量表达式
允许在同一个类型说明中,说明多个数组和多个变量。
int a, b, c, k1[10], k22[20];
二维数组
定义
多维数组元素有多个下标, 以标识它在数组中的位置,所以也称为多下标变量
声明的一般形式
类型说明符 数组名[常量表达式1][常量表达式2]…;
int a[3][4]
说明了一个三行四列的数组,数组名为a,其下标变量的类型为整型
该数组的下标变量共有3×4个
其中常量表达式1表示第一维下标的长度,
常量表达式2 表示第二维下标的长度
常量表达式2 表示第二维下标的长度
二维数组元素表示法
表示形式
数组名[下标][下标]
其中下标应为整型常量或整型表达式
赋值及初始化
赋值语句对数组逐个赋值
初始化赋值
二维数组初始化也是在类型说明时给各下标变量赋以初值
二维数组可按行分段赋值,也可按行连续赋值
按行分段赋值
static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} };
按行连续赋值
static int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85 };
说明
可以只对部分元素赋初值,未赋初值的元素自动取0值
static int a [3][3]={{0,1},{0,0,2},{3}};
如对全部元素赋初值,则第一维的长度可以不给出
static int a[3][3]={1,2,3,4,5,6,7,8,9};
static int a[][3]={1,2,3,4,5,6,7,8,9};
注意
数组是一种构造类型的数据
二维数组可以看作是由一维数组的嵌套而构成的
C语言允许分解二维数组
有二维数组a[3][4],可分解为三个一维数组,其数组名分别为a[0],a[1],a[2]
对这三个一维数组不需另作说明即可使用。这三个一维数组都有4个元素,
例如:一维数组a[0]的元素为a[0][0],a[0][1],a[0][2],a[0][3]。
必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量
例如:一维数组a[0]的元素为a[0][0],a[0][1],a[0][2],a[0][3]。
必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量
分类
数值数组
字符数组
定义
用来存放字符量的数组称为字符数组
使用
字符串在C语言中没有专门的字符串变量, 通常用一个字符数组来存放一个字符串
字符串总是以'\0'作为串的结束符
初始化赋值
用字符串的方式对数组作初始化赋值
exp
static char c[]={'c', ' ','p','r','o','g','r','a','m'};
static char c[]={"C program"};
sratic char c[]="C program";
`\0'是由C编译系统自动加上的
用printf函数和scanf函数一次性输出输入一个字符数组中的字符串
exp
void main()
{
static char c[]="BASIC\ndBASE";
printf("%s\n",c);
}
{
static char c[]="BASIC\ndBASE";
printf("%s\n",c);
}
void main()
{
char st[15];
printf("input string:\n");
scanf("%s",st);
printf("%s\n",st);
}
{
char st[15];
printf("input string:\n");
scanf("%s",st);
printf("%s\n",st);
}
不必使用循环语句逐个地输入输出每个字符
对一个字符数组,如果不作初始化赋值,则必须说明数组长度
当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符
void main()
{
char st1[6],st2[6],st3[6],st4[6];
printf("input string:\n");
scanf("%s%s%s%s",st1,st2,st3,st4);
printf("%s %s %s %s\n",st1,st2,st3,st4);
}
{
char st1[6],st2[6],st3[6],st4[6];
printf("input string:\n");
scanf("%s%s%s%s",st1,st2,st3,st4);
printf("%s %s %s %s\n",st1,st2,st3,st4);
}
scanf的各输入项必须以地址方式出现,如 &a,&b等。但在例4.8中却是以数组名方式出现的,
这是为什么呢?这是由于在C语言中规定,数组名就代表了该数组的首地址。
整个数组是以首地址开头的一块连续的内存单元
这是为什么呢?这是由于在C语言中规定,数组名就代表了该数组的首地址。
整个数组是以首地址开头的一块连续的内存单元
在执行函数printf("%s",c) 时,按数组名c找到首地址,
然后逐个输出数组中各个字符直到遇到字符串终止标志'\0'为止
然后逐个输出数组中各个字符直到遇到字符串终止标志'\0'为止
字符串常用函数
分类
输入
gets
格式
gets (字符数组名)
功能
从标准输入设备键盘上输入一个字符串
本函数返回一个函数值,即为该字符数组的首地址
注意
当输入的字符串中含有空格时,输出仍为全部字符串。
说明gets函数并不以空格作为字符串输入结束的标志, 而只以回车作为输入结束
说明gets函数并不以空格作为字符串输入结束的标志, 而只以回车作为输入结束
scanf函数以空格作为结束符
输出
puts
格式
puts (字符数组名)
功能
把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串
注意
puts函数中可以使用转义字符
puts函数完全可以由printf函数取代。 当需要按一定格式输出时,通常使用printf函数
合并
stract
格式
strcat (字符数组名1,字符数组名2)
功能
把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志“\0”
本函数返回值是字符数组1的首地址
注意
字符数组1应定义足够的长度,否则不能全部装入被连接的字符串
复制
strcpy
格式
strcpy (字符数组名1,字符数组名2)
功能
把字符数组2中的字符串拷贝到字符数组1中
串结束标志“\0”也一同拷贝。字符数名2, 也可以是一个字符串常量。
这时相当于把一个字符串赋予一个字符数组
这时相当于把一个字符串赋予一个字符数组
注意
字符数组1应有足够的长度,否则不能全部装入所拷贝的字符串
比较
strcmp
格式
strcmp(字符数组名1,字符数组名2)
功能
按照ASCII码顺序比较两个数组中的字符串,
并由函数返回值返回比较结果
并由函数返回值返回比较结果
字符串1=字符串2,返回值=0;
字符串2〉字符串2,返回值〉0;
字符串1〈字符串2,返回值〈0。
字符串2〉字符串2,返回值〉0;
字符串1〈字符串2,返回值〈0。
本函数也可用于比较两个字符串常量,或比较数组和字符串常量
测长
strlen
格式
strlen(字符数组名)
功能
测字符串的实际长度(不含字符串结束标志‘\0’)
并作为函数返回值
并作为函数返回值
修改
转换
搜索
指针数组
结构数组
函数
概述
函数是C源程序的基本模块, 通过对函数模块的调用实现特定的功能
C语言中的函数相当于其它高级语言的子程序
C语言不仅提供了极为丰富的库函数(如Turbo C,MS C 都提供了三百多个库函数),
还允许用户建立自己定义的函数
还允许用户建立自己定义的函数
用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数
函数的分类
函数定义角度
库函数
定义
由C系统提供,用户无须定义, 也不必在程序中作类型说明,
只需在程序前包含有该函数原型的头文件即可在程序中直接调用
只需在程序前包含有该函数原型的头文件即可在程序中直接调用
分类
字符类型分类函数
用于对字符按ASCII码分类:字母,数字,控制字符,分隔符,大小写字母等
转换函数
用于字符或字符串的转换;在字符量和各类数字量 (整型, 实型等)之间进行转换;在大、小写之间进行转换。
目录路径函数
用于文件目录和路径操作
诊断函数
用于内部错误检测
图形函数
用于屏幕管理和各种图形功能。
输入输出函数
用于完成输入输出功能
接口函数
用于与DOS,BIOS和硬件的接口
字符串函数
用于字符串操作和处理
内存管理函数
用于内存管理
数学函数
用于数学函数计算
日期和时间函数
用于日期,时间转换操作
进程控制函数
用于进程管理和控制
其它函数
用于其它各种功能
用户自定义函数
由用户按需要写的函数。对于用户自定义函数, 不仅要在程序中定义函数本身,
而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用
而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用
函数和过程角度
有返回值函数
此类函数被调用执行完后将向调用者返回一个执行结果, 称为函数返回值
用户定义的这种要返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型
无返回值函数
此类函数用于完成某项特定的处理任务, 执行完成后不向调用者返回函数值。
这类函数类似于其它语言的过程
这类函数类似于其它语言的过程
主调函数和被调函数之间数据传送的角度
无参函数
有参函数
注意
在一个函数的函数体内, 不能再定义另一个函数, 即不能嵌套定义。
但是函数之间允许相互调用,也允许嵌套调用
但是函数之间允许相互调用,也允许嵌套调用
习惯上把调用者称为主调函数
函数还可以自己调用自己,称为递归调用
main 函数是主函数,它可以调用其它函数,而不允许被其它函数调用
定义一个函数
无参函数的一般形式
类型说明符 函数名()
{
类型说明
语句
}
{
类型说明
语句
}
void Hello()
{
printf ("Hello,world \n");
}
{
printf ("Hello,world \n");
}
类型说明符和函数名称为函数头
类型说明符指明了本函数的类型,函数的类型实际上是函数返回值的类型
函数名是由用户定义的标识符,函数名后有一个空括号,其中无参数,但括号不可少
{} 中的内容称为函数体。在函数体中也有类型说明, 这是对函数体内部所用到的变量的类型说明
在很多情况下都不要求无参函数有返回值, 此时函数类型符可以写为void
有参函数的一般形式
传统格式
类型说明符 函数名(形式参数表)
形式参数类型说明
{
类型说明
语句
}
形式参数类型说明
{
类型说明
语句
}
int max(a,b)
int a,b;
{
if (a>b) return a;
else return b;
}
int a,b;
{
if (a>b) return a;
else return b;
}
现代格式
int max(int a,int b)
{
if(a>b) return a;
else return b;
}
{
if(a>b) return a;
else return b;
}
在进行函数调用时,主调函数将赋予这些形式参数实际的值
在C程序中,一个函数的定义可以放在任意位置, 既可放在主函数main之前,也可放在main之后
int max(int a,int b)
{
if(a>b)return a;
else return b;
}
void main()
{
int max(int a,int b);
int x,y,z;
printf("input two numbers:\n");
scanf("%d%d",&x,&y);
z=max(x,y);
printf("maxmum=%d",z);
}
{
if(a>b)return a;
else return b;
}
void main()
{
int max(int a,int b);
int x,y,z;
printf("input two numbers:\n");
scanf("%d%d",&x,&y);
z=max(x,y);
printf("maxmum=%d",z);
}
程序的第1行至第5行为max函数定义。进入主函数后,因为准备调用max函数,故先对max函数进行说明(程序第8行)。
函数定义和函数说明并不是一回事,在后面还要专门讨论。
可以看出函数说明与函数定义中的函数头部分相同,但是末尾要加分号。
程序第12 行为调用max函数,并把x,y中的值传送给max的形参a,b。
max函数执行的结果 (a或b)将返回给变量z。最后由主函数输出z的值
函数定义和函数说明并不是一回事,在后面还要专门讨论。
可以看出函数说明与函数定义中的函数头部分相同,但是末尾要加分号。
程序第12 行为调用max函数,并把x,y中的值传送给max的形参a,b。
max函数执行的结果 (a或b)将返回给变量z。最后由主函数输出z的值
函数的调用
一般形式
函数名(实际参数表)
实际参数表中的参数可以是常数,变量或其它构造类型数据及表达式
各实参之间用逗号分隔
函数调用的方式
函数表达式
函数作表达式中的一项出现在表达式中,以函数返回值参与表达式的运算
z=max(x, y)
这种方式要求函数是有返回值的
函数语句
函数调用的一般形式加上分号即构成函数语句
z=max(x, y);
printf("%d", a);
printf("%d", a);
函数实参
函数作为另一个函数调用的实际参数出现
printf("%d", max(x, y));
这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的
注意
在函数调用中还应该注意的一个问题是求值顺序的问题。
所谓求值顺序是指对实参表中各量是自左至右使用呢,还是自右至左使用。
对此, 各系统的规定不一定相同
所谓求值顺序是指对实参表中各量是自左至右使用呢,还是自右至左使用。
对此, 各系统的规定不一定相同
调用时对被掉函数的说明
对被调函数的说明的两种格式
传统
类型说明符 被调函数名();
现代
类型说明符 被调函数名(类型 形参,类型 形参…);
在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型, 以便在主调函数中按此种类型对返回值作相应的处理
函数的嵌套调用
在被调函数中又调用其它函数
函数的递归调用
一个函数在它的函数体内调用它自身称为递归调用。 这种函数称为递归函数。
为了防止递归调用无终止地进行, 必须在函数内有终止递归调用的手段。
常用的办法是加条件判断, 满足某种条件后就不再作递归调用,然后逐层返回
常用的办法是加条件判断, 满足某种条件后就不再作递归调用,然后逐层返回
可以省去主调函数中对被调函数的函数说明的情况
如果被调函数的返回值是整型或字符型时, 可以不对被调函数作说明,而直接调用。
这时系统将自动对被调函数返回值按整型处理
这时系统将自动对被调函数返回值按整型处理
当被调函数的函数定义出现在主调函数之前时, 在主调函数中也可以不对被调函数再作说明而直接调用
如在所有函数定义之前, 在函数外预先说明了各个函数的类型,则在以后的各主调函数中,可不再对被调函数作说明
对库函数的调用不需要再作说明, 但必须把该函数的头文件用include命令包含在源文件前部
函数的参数
形参
形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元,
因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量
因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量
实参
实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,
在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参
在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参
数组作为函数的参数
数组元素(下标变量)作为实参使用
数组名作为函数的形参和实参使用
用数组名作函数参数时, 则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。
数组名作函数参数时所进行的传送只是地址的传送, 也就是说把实参数组的首地址赋予形参数组名。
形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间
形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间
由于实际上形参和实参为同一数组, 因此当形参数组发生变化时,实参数组也随之变化。
当然这种情况不能理解为发生了“双向”的值传递
当然这种情况不能理解为发生了“双向”的值传递
注意
实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误
函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化
因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化
函数的返回值
说明
函数的值只能通过return语句返回主调函数
return 语句的一般形式
return 表达式;
或者为:
return (表达式);
或者为:
return (表达式);
在函数中允许有多个return语句,但每次调用只能有一个return 语句被执行, 因此只能返回一个函数值
函数值的类型和函数定义中函数的类型应保持一致。
如果两者不一致,则以函数类型为准,自动进行类型转换
如果两者不一致,则以函数类型为准,自动进行类型转换
如函数值为整型,在函数定义时可以省去类型说明
不返回函数值的函数,可以明确定义为“空类型”, 类型说明符为“void”
内部函数和外部函数
出现缘由
函数一旦定义后就可被其它函数调用。 但当一个源程序由多个源文件组成时, 在一个源文件中定义的函数能否被其它源文件中的函数调用呢?
分类
内部函数
定义
如果在一个源文件中定义的函数只能被本文件中的函数调用,
而不能被同一源程序其它文件中的函数调用, 这种函数称为内部函数
而不能被同一源程序其它文件中的函数调用, 这种函数称为内部函数
定义内部函数的一般形式
static 类型说明符 函数名(形参表)
static int f(int a,int b)
内部函数也称为静态函数。但此处静态static 的含义已不是指存储方式,
而是指对函数的调用范围只局限于本文件。 因此在不同的源文件中定义同名的静态函数不会引起混淆。
而是指对函数的调用范围只局限于本文件。 因此在不同的源文件中定义同名的静态函数不会引起混淆。
外部函数
定义
外部函数在整个源程序中都有效
定义外部函数
extern 类型说明符 函数名(形参表)
extern int f(int a,int b)
如在函数定义中没有说明extern或static则隐含为extern。
在一个源文件的函数中调用其它源文件中定义的外部函数时,应用extern说明被调函数为外部函数
在一个源文件的函数中调用其它源文件中定义的外部函数时,应用extern说明被调函数为外部函数
变量
变量的存储方式
静态存储变量
静态存储变量通常是在变量定义时就分定存储单元并一直保持不变, 直至整个程序结束
动态存储变量
动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放
典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,
只是在函数被调用时,才予以分配, 调用函数完毕立即释放
只是在函数被调用时,才予以分配, 调用函数完毕立即释放
变量的特性
生存期
生存期表示了变量存在的时间
作用域
生存期表示了变量存在的时间
变量的存储类型
auto
自动变量
定义
语言规定, 函数内凡未加存储类型说明的变量均视为自动变量,
也就是说自动变量可省去说明符auto。
也就是说自动变量可省去说明符auto。
特点
自动变量的作用域仅限于定义该变量的个体内。在函数中定义的自动变量,
只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效
只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效
自动变量属于动态存储方式,只有在使用它,即定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。
函数调用结束,释放存储单元,结束生存期。
因此函数调用结束之后,自动变量的值不能保留。在复合语句中定义的自动变量,在退出复合语句后也不能再使用,否则将引起错误
函数调用结束,释放存储单元,结束生存期。
因此函数调用结束之后,自动变量的值不能保留。在复合语句中定义的自动变量,在退出复合语句后也不能再使用,否则将引起错误
由于自动变量的作用域和生存期都局限于定义它的个体内( 函数或复合语句内),
因此不同的个体中允许使用同名的变量而不会混淆。
因此不同的个体中允许使用同名的变量而不会混淆。
对构造类型的自动变量如数组等,不可作初始化赋值
register
寄存器变量
定义
种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写, 这样可提高效率
特点
只有局部自动变量和形式参数才可以定义为寄存器变量。因为寄存器变量属于动态存储方式。
凡需要采用静态存储方式的量不能定义为寄存器变量。
凡需要采用静态存储方式的量不能定义为寄存器变量。
在Turbo C,MS C等微机上使用的C语言中, 实际上是把寄存器变量当成自动变量处理的。
因此速度并不能提高。 而在程序中允许使用寄存器变量只是为了与标准C保持一致。
因此速度并不能提高。 而在程序中允许使用寄存器变量只是为了与标准C保持一致。
即使能真正使用寄存器变量的机器,由于CPU 中寄存器的个数是有限的,因此使用寄存器变量的个数也是有限的。
extern
外部变量(全局变量)
定义
它是在函数外部定义的变量。 它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序
在函数中使用全局变量,一般应作全局变量说明。 只有在函数内经过说明的全局变量才能使用。
全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。
全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。
特点
外部变量和全局变量是对同一类变量的两种不同角度的提法。
全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。
全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。
当一个源程序由若干个源文件组成时, 在一个源文件中定义的外部变量在其它的源文件中也有效。
static
静态变量
静态局部变量
定义
局部变量的说明前再加上static说明符就构成静态局部变量
特点
静态局部变量在函数内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。
静态局部变量始终存在着,也就是说它的生存期为整个源程序
静态局部变量始终存在着,也就是说它的生存期为整个源程序
静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。
退出该函数后, 尽管该变量还继续存在,但不能使用它。
退出该函数后, 尽管该变量还继续存在,但不能使用它。
允许对构造类静态局部量赋初值。在数组一章中,介绍数组初始化时已作过说明。若未赋以初值,则由系统自动赋以0值。
对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。
总结
根据静态局部变量的特点, 可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
静态全局变量
总结
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
总结
把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它
的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。
的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。
变量说明的完整形式
存储类型说明符 数据类型说明符 变量名,变量名…;
static int a,b; 说明a,b为静态类型变量
auto char c1,c2; 说明c1,c2为自动字符变量
static int a[5]={1,2,3,4,5}; 说明a为静整型数组
extern int x,y; 说明x,y为外部整型变量
auto char c1,c2; 说明c1,c2为自动字符变量
static int a[5]={1,2,3,4,5}; 说明a为静整型数组
extern int x,y; 说明x,y为外部整型变量
变量的作用域
变量作用域的定义
定义
变量有效性的范围称变量的作用域
注意
不仅对于形参变量, C语言中所有的量都有自己的作用域
变量说明的方式不同,其作用域也不同
局部作用域
局部变量
定义
局部变量是在函数内作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的
注意
主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。
因为主函数也是一个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意
因为主函数也是一个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意
形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量
允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。
在复合语句中也可定义变量,其作用域只在复合语句范围内
全局作用域
全局变量
定义
它是在函数外部定义的变量。 它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序
在函数中使用全局变量,一般应作全局变量说明。 只有在函数内经过说明的全局变量才能使用。
全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。
全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。
exp
int a,b; /*外部变量*/
void f1() /*函数f1*/
{
……
}
float x,y; /*外部变量*/
int fz() /*函数fz*/
{
……
}
main() /*主函数*/
{
……
}/*全局变量x,y作用域 全局变量a,b作用域*/
void f1() /*函数f1*/
{
……
}
float x,y; /*外部变量*/
int fz() /*函数fz*/
{
……
}
main() /*主函数*/
{
……
}/*全局变量x,y作用域 全局变量a,b作用域*/
a、b、x、y 都是在函数外部定义的外部变量,都是全局变量。但x,y 定义在函数f1之后,而在f1内又无对x,y的说明,所以它们在f1内无效。 a,b定义在源程序最前面,因此在f1,f2及main内不加说明也可使用
注意
对于局部变量的定义和说明,可以不加区分。而对于外部变量则不然,外部变量的定义和外部变量的说明并不是一回事。
外部变量定义必须在所有的函数之外,且只能定义一次。其一般形式为: [extern] 类型说明符 变量名,变量名… ;
其中方括号内的extern可以省去不写
外部变量定义必须在所有的函数之外,且只能定义一次。其一般形式为: [extern] 类型说明符 变量名,变量名… ;
其中方括号内的extern可以省去不写
extern int a, b;
int a, b;
而外部变量说明出现在要使用该外部变量的各个函数内, 在整个程序内,可能出现多次,
外部变量说明的一般形式为: extern 类型说明符 变量名,变量名,…;
外部变量在定义时就已分配了内存单元, 外部变量定义可作初始赋值,外部变量说明不能再赋初始值, 只是表明在函数内要使用某外部变量。
外部变量说明的一般形式为: extern 类型说明符 变量名,变量名,…;
外部变量在定义时就已分配了内存单元, 外部变量定义可作初始赋值,外部变量说明不能再赋初始值, 只是表明在函数内要使用某外部变量。
外部变量可加强函数模块之间的数据联系, 但是又使函数要依赖这些变量,因而使得函数的独立性降低。
从模块化程序设计的观点来看这是不利的, 因此在不必要时尽量不要使用全局变量
从模块化程序设计的观点来看这是不利的, 因此在不必要时尽量不要使用全局变量
在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。
指针
结构和联合
枚举、位运算
预处理
文件
0 条评论
下一页