导图社区 C语言
这是一篇关于C语言的思维导图,主要内容包括:指针,函数,数组,循环,switch语句,if语句,逻辑运算符和逻辑表达式,关系运算符和关系表达式,简单的C程序,数据类型,运算符和表达式,概述,考试题型。
编辑于2025-03-01 10:32:53C语言
考试题型
单选题
判断题
程序填空
程序分析
编程题
概述
计算机发展
程序设计语言的发展
C语言的发展
C语言的特点
中级语言
访问硬件
程序员语言
运输符丰富,代码质量高,可移植性好
模块化设计语言
C语言程序结构
说明
C程序的构成
函数由两部分构成
程序的执行
语句
编程风格
整体结构 对齐
标识符的定义,望文知意
注释
上机步骤
编辑
源程序输入
修改源程序
保存
编译
检查语法错
生成目标程序 .obj
链接
库函数
执行
.exe文件
数据类型,运算符和表达式
程序=数据结构+算法+程序设计方法+程序设计语言和环境
数据类型
基本类型
整型
字符型
实型
构造类型
数组
结构体
共用体
枚举类型
指针类型
void类型
函数类型
常量与变量
常量
程序执行过程中,其值不会改变的量
直接常量(字面常量)
符号常量
变量
其值可以改变的量
变量有一个名字
编译时分配存储单元
标识符
标识符就是一个名字
分类
关键字
预定义标识符
printf
scanf
用户标识符
由字母数字下划线构成
开头只能是字母或下划线
不能和保留字重复
区分大小写
注意长度
变量的定义
先定义后使用
定义的格式
类型名称 变量名1,变量名2;
位置
全局变量
函数外
局部变量
一般在函数开头
复合语句开头
数据类型
整型数据
整型常量
十进制
123,-456
八进制
以0(零)开头
011 =》9
-017=》-15
018、019=》错
十六进制
以0X开头
后加L或l(小写),认为长整型常量
0L
后加U或u,是unsigned无符号
123U
整型变量
int a;
VC++6.0内存中占4字节
分类
修饰符
signed
unsigned
short
2字节
long
4字节
实型数据
实型常量
实数也称为浮点数
表示形式
十进制
由数和小数点构成
0.123 .123 123.
指数形式
123e3 或 123E3 =》123*10^3
注:e的前后必须有数,且e后的指数为整数
如: e3, 2.13e3.5, .e, e 错
实型变量
单精度
float
4字节
有效数字6-7
双精度
double
8字节
15-16
长双精度
long double
字符型数据
字符常量
用单引号括起来的一个字符
如: 'A', 'a' 不同, ''连续的两个单引号,错
转义字符
特殊形式的字符以“\"开头
'\n', '\t',
'\ddd' 1-3位八进制对应的ASCII码字符
char ch = '\101';
‘\xhh' 1-2位十六进制
char a = '\x61';
字符变量
用于存放字符常量,只能存放一个,占1字节
定义形式
char 字符变量1,字符变量2;
char c1, c2; c1 = 'a'; c2 = 97;
字符数据在内存中的存储形式
存放该字符对应的ASCII码
与整型相似,可以和整型通用
0-127最高位是0,以%d输出得正值 128-255最高位是1,%d输出是负值
字符串常量
用双引号括起来的字符序列
注意: “a”, 和 ‘a‘区别
连续的两个“”,正确
区别
表示形式不同
双引号“
单引号’
子主题 3
定义不同
char ch;字符变量存放字符常量
字符数组存放字符串
引用
两者不可相互引用
内存中存放
内存中占1字节
串:以'\0'结束 内存中所占字节数=实际字符长度+1 如:“CHINA"5个字符,在内存中占6个字节
特点
只有字符串常量没有字符串变量
字符串以'\0'结束,没有'\0'不能称之为一个串,
4个零
0
数字0,累加器,计数器,数组的下标
'\0'
串的结束符,ASCII码值0,也是不可显示字符
NULL
一般用于个指针赋值,指向为空
‘0’
字符0, ASCII值48
char-char =》int
'7' - '0' => 7
char + int => char
//大小写转换 char ch = 'B'; char st = ch - 'A' + 'a'; st = 'a' + 'A' - ch
char + char 无意义
变量赋值
变量在定义时赋初值称为初始化
int a = 10;
int a; a = 10;
int a, b, c=10;
int a, b, c; c = 10;
int a = b = c = 10; 错
int a, b, c; a = b = c =10;
知半径求周长,面积,球的体积
符号常量
定义
#define PI 3.14
用PI替换3.14
特点
简化书写,易读
修改方便
说明
一般用大写,变量小写
作用域
从#define 开始
到 #undef 或文件尾结束
在作用域内不可修改符号常量的值
const double PI = 3.14;
各类数值型数据的混合运算
混合运算
高 double
←float
↑long
↑unsigned
低 int
←char,short
横向箭头,表示必须的转换
如两个float类型的变量运算也要, 先转换为double再运算,结果为double类型
纵向箭头,表示转换方向
int与double运算,将int直接转换为double与double运算, 结果为double
运算结果
参与运算的,类型最高的
练习
ch/i + f*d - ( f + i )
算术运算符和算术表达式
运算符特点
算术运算符
组成
+ - * / % ++ --
%取模运算符
运算对象只能整型
结果与被除数的符号相同
应用:拆数
n = 123分别取出个位、十位和百位
个位 n%10 十位 n/10%10 n%100/10 百位 n/100
除以10, 降阶
对10求余, 得个位
运算符的优先级与结核性
求值先看优先级
() 单目
优先级相同,看结合性
左结合:符合算术运算规则,从左到右
右结合:
单目
赋值运算符
条件运算符
练习
下列一组运算符由高到低排列的是_____
强制类型转换(显示转换)
5.7%3 =》?
格式 (类型名)(表达式)
如: (int)5.7%3
(double)x + y
将x+y的结果,转化为double?
(double)(x + y)
将x值转换为double后与y相加
用途
函数参数
注意
不安全的转换
高精度-》低精度, 直接截取(不是四舍五入)
低精度-》高精度, 补0
暂时的一次性
(int)x + y
将x值转换为int后与y相加,x本身的值不变
double x = 5.7 (int)x + 3.2 结果:5+3.2 = 8.2 x是5.7不变
自增自减运算符
单目运算符++, --
运算对象:只能用于变量,本身也是一种赋值运算
3++, (a+b)++ 错
i = 3;
j = i++;
运算符++,在右,先使用i的值,然后i完成加1操作
j = i;
i = i + 1;
j = ++i;
运算符++在左,先完成i的加1操作,然后将i的值(+1后)赋给j
i = i + 1;
j = i;
练习
int a = 3; while( a-- ) printf("%d ", a ); printf(" \n out while %d", a ); 2 1 0 out while -1
int a = 3; while( --a ) printf("%d ", a ); printf(" \n out while %d", a ); 2 1 out while 0
注意
结合性右结合,自右至左
int a = 3; printf(" %d\n", -a++ ); printf(" %d\n", a );
i++ ;与 ++i;
没有区别,完成 i=i+1;
赋值运算符和赋值表达式
赋值符号 =
格式: 变量名 = 表达式
作用:将右边表达式的值赋给左边的变量
如 a = 10 将10赋给a,执行一次赋值操作 (把10放入a的存储单元中)
注意
结合性:右结合
左侧一定是不变量,不能是常量或表达式
d = a + b = c + 10; 错
不同数据类型之间的相互赋值
实型(float,double)给整型(int),舍弃小数部分,不是四舍五入, 需要四舍五入 +0.5
int=》float、double, 数值不变,以浮点形式存储,尾部补0
char=》int , char1个字节,int 4字节,放入低8位中
非unsigned与类型相同的unsigned相互赋值
double=》float 截取将double前7位有效数字赋值给float
练习
将浮点数n保留2位小数,第3位四舍五入 如 n=3.4567 结果为: 3.46
复合运算符(算术字符赋值运算符)
优先级
结合性(右)
构成
+=, -=, *=, &=, ^=, !=(关系)
注意
x += 3;
x = x +3;
x *= y+3;
x = x *(y+3)
赋值号右边含有若干项,相当于有括号
练习
a=3; a += a -= a * a
赋值表达式
赋值是运算符
右结合
表达式有值
逗号表达式和逗号运算符
格式: 表达式1, 表达式2
求解过程
逗号,左结合
优先级最低
先求解表达式1,……,将最右端的表达式的值作为整个逗号表达式的值
练习
x = ( y=3, 4*5 )
x 值20
x = y=3, 4*5
x 值 3, 整个逗号表达式的值是 20
用途
表达式串联
for( i=1,j=100; i<j; i++,j-- );
分隔符
int x, y;
求长度运算符
sizeof(变量|常量|类型)
求该类型在内存中所占字节数
malloc( sizeof( struct link ) )
简单的C程序
C语句概述
控制语句
函数调用语句
函数(实参表列);
scanf(“%d“,a);
表达式语句
空语句
复合语句
用{}括起来的
注意
在语法是相当于一条语句,作为一个整体
复合语句开始部分可以定义变量
复合语句的}后,不用加;
程序的三种基本结构
顺序结构
选择(分支)结构
循环(重复)结构
赋值语句
语句 ;
与表达式区别
表达式有值概念
数据输入/出
没有输入输出语句,只有输入输出函数
stdio.h头文件
标准输入输出头文件
输出
putchar(ch) 字符输出函数
向终端输出一个字符
ch可以是char、int常量、变量、表达式
printf(格式控制,输出表列)
格式控制是由 双引号括起来的字符串
格式说明
%和格式字符组成 %d
普通字符
原样输出,空格 逗号
格式字符
不同的数据类型,采用不同的格式字符
d格式
输出十进制整型
%d按实际长度输出
%md,m输出字段宽度, 若实际位数小于m,左补空格(右对齐) 若实际位数大于m,突破
%-md -(负号)对齐方式,,左对齐(右补空格)
%ld长整型, %hd 短整型
O格式
以八进制形式输出
符号位一起输出
X格式
以十六进制形式输出
%lx
U格式
无符号形式输出,十进制
c格式
用于输出一个字符
字符内存中占一个字节,存储的是ASCII码 0-255可以按数值输出,
s格式
用于输出一个字符串
%s 直至遇见'\0'
%ms
%-ms
%m.ns
输出占m列,取字符串的前n个字符
%-m.ns
f格式
用于输出实数,float和double,以小数形式输出
%f
整数部分全部输出,并输出6位小数
注意
并非全部数值都有效
%m.nf
输出占m列,其中n位小数
注意
小数点也占一位
取n位时,截去的第一位四舍五入
%.0f 不输出小数部分
%-m.nf
e格式
以指数形式输出实数
%e
系统指定6位小数,指数部分占3位,e占一位,±占一位
%m.ne
g格式
用于输出实数,自动选取f或e格式中宽度最短的
使输出的数字前代正负号
printf("%+5d%+d\n", a, b );
注意
除X,E,G其他格式字符小写
数据类型与格式字符匹配
类型
个数
格式控制字符串中,可以包含转义字符
d,o,u,x,s,c,f,e,g,在%之后为格式字符,其他原样输出
输出%,使用%%
系统不同有差别
输入
getchar()
字符输入,从终端输入一个字符
getchar()无参数
scanf(格式控制,地址表列)
格式控制与printf相同
格式字符
普通字符原样输入
地址表列,变量的地址,字符串首地址
注意:%d%d,以空格、tab键、回车做间隔 不能使用 , 逗号
格式说明
short用%hd,double用%lf或%le输入
对unsigned可以用%u,%d, %o,%x输入
可以指定输入数据的域宽,系统自动截取
%后带有*,表示跳过指定的列数
列数可以指定,精度不可以指定
scanf(“%7.2f“, &f );错
注意
scanf函数,应给出变量的地址
普通字符原样输入
%c输入字符时,空格,转义字符均作为有效输入
输入数据时遇到以下情况认为结束
遇空格、Tab键、回车
遇指定域宽%3d
遇非法输入
关系运算符和关系表达式
关系实际就比较运算
关系运算符
>, >=, <, <=
!=, ==
优先级
低于算术
结合性
左结合
关系表达式
链接任何合法的表达式
值:是一个逻辑值
真用1表示,假用0表示
练习
a = 20; b = 10; a>b的值是 1
a=3; b=2; c=1; a>b>c的值是 0
注意
两边类型不一致,如int与double运算,系统自动转换
判相等
int a==b?
fabs(a-b)<1e-6
逻辑运算符和逻辑表达式
逻辑运算符
&&, ||, !
优先级
! 单目运算符
低于关系 &&高于||
逻辑表达式
值:逻辑值,真用1表示,假用0表示
参与运算的对象,非零代表真,零代表假
注意
求解过程中不是所有的逻辑运算都执行
短路现象
练习
if语句
if语句的三种形式
单分支的if语句
格式: if(表达式)语句;
表达式:任意合法的表达式
if(3);
语句:可以是单语句、空语句或复合语句
练习
由小到大顺序输出两个整数
双分支的if语句
格式: if(表达式) 语句1; else 语句2;
注意:else与if对齐
练习
偶数n为真的表达式
n%2==0
n/2*2 == n
!(n%2)
ch是英文字母
ch>='a'&&ch<='z' || ch>='A'&&ch<='Z'
判断闰年
能被4整除,不能被100整除 能被4整除,同上能被400整除
year%4==0&&year%100!=0 || year%400==0
year%4==0&&year%100 || !(year%400)
整数a、b为同号
a*b>0
阶梯型的if语句
格式: if(表达式1) 语句1; else if(表达式2) 语句2;
if( x<0 ) y = -1; else if( x==0 ) y = 0; else y = 1;
嵌套的if语句
if( x>=0 ) if( x>0 ) y = 1; else y = 0; else y = -1;
注意:if与else配对关系,从最内层开始,else总是与它上面的最近的,未曾配对的if配合使用
解决方法:
内嵌的if语句也含有else,if与else的数目一样多
使用花括号嵌套,限定内嵌if语句的作用范围
练习
条件运算符
构成
?和:
优先级:算术,关系,逻辑,条件, 赋值,逗号
结合性:右结合
条件表达式
表达式1?表达式2:表达式3
求值次序:先求解表达式1,真求解2,假求解3, 并以该值作为整个表达式的值
表达式2和3只会求解一个
说明
结合性:右结合
int a = 1, b = 2, c = 3, d = 4; printf("%d\n", a>b ? a:c>d ?c:d );
类型
表达式1、2、3的类型可以不同
a>b ? 1.5:2
值为类型高的
与if语句的关系
当if语句的真和假给同一个变量赋值
if( a>b ) max = a; else max = b;
max = a>b ? a:b;
switch语句
处理多分支
格式: switch( 表达式 ) { case 情况1: 语句1; …… default: 语句 n+1; }
说明
switch后括号中的表达式一般是,字符型,整型,枚举类型
情况的取值与表达式类型相同的常量表达式
情况的作用相当于一个标号,代表入口,执行后面的语句直至最后,没有匹配的执行default后面语句
终止语句的执行需使用break,可以直接跳出该switch语句
每种情况必须不同,否则矛盾
各case和default语句出现的顺序不影响,执行结果(与break配合使用)
多个case语句可以共用一组语句
练习
循环
if和goto构成的循环
goto语句
格式:goto 语句标号;
语句标号符合标识符的命名规则
goto label;
注意
标号后必须有:,放在某条语句之前,作为该语句的代号
跳转的位置
本函数内
一般和if构成循环
尽量少用,从多重循环中跳出
for( ) for() for() if() goto end;
while
格式 while(表达式) 语句;
特点
先判断表达式的值,真执行语句,假退出
注意
if、while、for有效作用范围到第一个分号处结束
语句可以是单语句、复合语句、空语句
循环体(语句)中应当有使循环趋于结束的语句
while( 1 ) x++;
死循环
i = 100; while( i>10 ) a + b;
while( x = 'a' ); 和 while( x==‘a' )区别
k = 2; while( k=0 ) k--;
循环体执行?次
练习
1+2+……+100
do-while
格式 do 语句; while(表达式);
特点
先执行循环体,判断表达式的值,真执行,假退出
注意
和while循环区别
循环变量初值,while可能一次也不执行循环体 do-while至少执行一次
相同点
真执行,假退出
练习
拆数与拼数
拆数
%10 得,尾数
/10 降阶
拼数
低位变高位,高位变低位
(0*10)+a)*10+b)*10+c
高位和低位保持不变
t = 1; s += n%10 * t; t *=10;
do 语句; while( 1 );
死循环
for
格式: for( 表达式1;表达式2;表达式3) 语句;
说明
表达式1,只执行1遍
可以省略各表达式,分号不能省略
表达式1和表达式3可以是简单表达式,也可以是逗号表达式
练习
嵌套
乘法口诀 表
打印图形
穷举
几种循环的比较
解决问题
四种循环可以相互替换,不提倡if和goto构成的循环
初始化
while,do-while在循环外,for表达式1
终止条件
while,do-while在while后,for 表达式2
i = 3; while(i--); while(--i); 区别
执行顺序
while和for先判断后执行,do-while是先执行后判断
跳出循环
while,do-while,for都可以使用break跳出, continue结束本次循环
break
跳出循环体,提前结束循环
练习
判素数
从键盘输入某个正整数,输出大于等于该数的5个素数 如输入 17,则输出 17,19,23,29,31
continue
结束本次循环,跳过循环体中,尚未执行的语句,进行下次是否循环的判断(while,for执行表达式3)
数组
一维数组定义和引用
数组是类型相同的数据元素的集合 数组名
定义
数据类型 数组名[整型常量表达式];
数组名:地址常量,代表数组的起始地址
int a[10];
#define N 10 int a[N];
引用
数组名[下标]
下标从0开始,到N-1
下标整型常量、变量、表达式
初始化
全部元素赋初值
int a[3]={1,2,3};
全部元素赋初值,可不指定长度 int a[] = { 1,2,3}; int a[] = { 0 };
部分元素赋初值
int a[10] = { 1,2,3}; a[1]=2, a[3]--a[9] = 0
省略的部分元素值为默认值
int a[3] = { 0,0,0};与int a[3]={0};等价
int a[10];与static int a[10];的区别
当数组长度N与元素格式M不一致时
N>M,只给数组的前M个元素赋初值,其余为默认值
N<M,语法错
应用
元素逆序排列
折半查找
排序
冒泡排序
选择排序
运算
插入
先移动后面的
删除
先移动前面的
移动(循环左移、右移)
二维数组
定义
数据类型 数组名[整型常量表达式1][整型常量表达式2];
内存中按行存放,行序优先
int a[N][M]; N行,M列,a[i][j]之前有多少元素i*M + j
引用
数组名[行下标][列下标]
初始化
与一维数组相同,逐个元素赋初值,顺序给出
int a[2][3] = { 1,2,3,4,5,6};
全部元素赋初值可以省略第1维大小
int a[][3] = { 1,2,3,4,5,6,7};
分行赋初值,使用花括号
int a[2][3] = { {1,2,3},{4,5,6}};
int a[2][3] = { {1,2},{3,4},{5,6}};
错
对部分元素赋初值
int a[3][4] = { {2}, {4}, {6} }; int a[3][4] = { {2}, {0,4}, {0,0,6} };
应用
行列下标
杨辉三角形
特殊方阵
螺旋方阵
字符数组
定义
char 数组名[整型常量表达式];
初始化
逐个元素赋初值
char ch[] = { 'a', 'b', 'c' };
指定一个字符串作为初值
char ch[] = { "hello"};
char ch[] = "hello";
char ch[] = { 'h','e','l','l','o','\0'};
字符数组与字符串的区别
字符数数组中的每个元素是一个字符, 不要求最后一个元素是'\0'
字符串的结束符是'\0'
字符数组的输入/出
字符串的单个字符输入输出
for( i=0; i<5; i++ ) printf("%c %d | ", ch[i], ch[i] );
访问每个元素
字符串的输入、输出
%s格式
char ch[80]; scanf("%s", ch ); printf("%s", &ch[3] );
scanf("%s", ch );
表明输入的字符从内存的哪个地址开始存放
遇回车,TAB键,空格结束
结束时 系统自动补 '\0'
printf("%s", ch );
ch为数组的首地址,%s后面跟地址, 代表从此地址开始输出,遇'\0'结束
注意
数组名代表数组的起始地址,不应再&, &ch错,可以 &ch[0]
可以从数组的中间输入、输出
scanf("%s", &ch[3] ); printf("%s", ch );
字符串处理函数
字符串输出函数
puts( ch);
ch可以是字符数组名
字符指针
字符串常量
与%s的区别
puts输出后自动换行
字符串输入函数
gets(ch);
ch可以是字符数组名
字符指针(确切的指向)
gets(s1,s2);错
与%s输入的区别
gets只能以回车结束
字符串处理函数 string.h
字符串链接 strcat( 字符数组1,字符串2 )
前者一定是变量,且空间大小能放下两个字符数之和
后者,常量变量均可
结果只保留后者中的'\0'
练习
串拷贝 strcpy( 字符数组1,字符串2 )
前者一定是变量,且空间大小能放下两个字符数之和
后者,常量变量均可
结果是将字符2,'\0'之前的内容拷贝到字符数组中, '\0'也一起拷贝过去
练习
strncpy( str1,str2, n )
将str2中的前n个字符拷贝到str1中
不拷贝'\0'
字符串比较 strcmp( 字符串1,字符串2 )
常量变量均可
顺序:从左至右逐个比较字符的ASCII值
结束:遇'\0',或不同字符
结果:0表示相等,1>2正值 1, 1<2负值-1
判断连个字符串是否相等
if( strcmp(s1,s2)==0 ) ;
字符串长度strlen(字符串)
求实际字符串的长度,不包括'\0'
第一个'\0'之前的字符个数
练习
转换小写 strlwr(字符串)
转换大写strupr(字符串)
练习
删除字符串中的特殊字符
字符串拷贝
串比较
串连接
统计单词个数
统计子串在主串中出现的次数
用筛选法求100以内的素数
插入、删除
函数
概述
定义:能够完成特定功能的一段程序
注意
编译单位:文件
以源程序为单位进行编译
C的执行是从main函数开始的
所有函数都是平行的,即函数定义是相互独立的
定义不能嵌套
函数之间可以相互调用,不能调用main函数
函数调用可以嵌套
分类
用户角度
用户函数
用户定义,用于解决专门问题
系统函数
标准函数,scanf
函数自身形式
有参函数
sqrt(n)
无惨函数
getchar()
返回值的角度
有返回值的
strcmp(s1,s2); pow(x,y );
无返回值的
作用范围的角度
外部函数
内部函数
函数定义
有参函数定义格式
无参函数的定义格式
空函数
dummy(){ }
函数参数和函数的值
参数
形参
定义函数,括号中
被调
实参
调用函数使用参数
主调
说明
定义函数时,必须指定形参的类型
格式:数据类型 形参名
实参可以是常量、变量、表达式,但是要有确切的值
形参存储单元的分配和释放
调用时分配,将实参的值拷贝给形参,调用结束释放
实参到形参单向值传递,形参与实参分配不同的存储单元,修改形参不影响实参
函数的返回值
函数的返回值,是通过return语句获得的
return语句的数量,多个,执行到那个,哪个起作用
return语句后的括号可以省略, 可以是常量,变量,表达式要求有确切的值
函数值的类型
函数返回值的类型
在定义时确定的
函数类型与return语句返回的类型不一致
函数类型决定返回值的类型
函数中无return语句
返回一个不确定值,除非定义为void
不需要返回值,定义为void
仍然可以使用return,但其后不能有值
函数默认返回值类型为 int
函数的调用
一般格式
函数名(实参表列);
多个参数之间用 逗号 间隔
参数的个数,顺序,类型(赋值兼容)一致
调用方式
函数语句
printf(“OK”);
函数表达式
x = 10 * sqrt( y );
函数参数
max( max( x, y ), z );
调用过程
形参分配存储单元,实参值 赋值 给 形参
实参 -》形参 单向值传递
多个函数嵌套调用时,按照 先调用的后返回
遇 return 语句, 或 右花括号 } 结束
对被调函数的声明和函数原型
调用另一个函数,具备条件
被调函数必须存在 (即已定义的函数)
库函数
scanf
自定义函数
max(x, y )
使用库函数
在文件开头使用#include 包含对应的头文件
stdio.h
math.h
abs(), fabs(),pow(),sin()
string.h
strcpy(),strcat(),strcmp()
strlen()
ctype.h
malloc.h(stdlib.h)
malloc(),free(),calloc()
自定义函数
对被调函数进行声明
定义和声明的区别
意义
函数类型 函数名,形参表列和一个完整的函数体 定义是对函数功能的确立
对已定义(存在)的函数进行
个数
同名称,在一个文件中,只有一个
多个
位置
函数的定义不能嵌套
在哪个函数内调用,在哪声明 所有函数外,文件开头
作用域
内部函数(该文件),外部函数(其他文件)
声明它的函数 声明它的文件
函数原型
C语言的函数声明称为函数原型
函数类型 函数名( 参数类型1 形参1, 参数类型2 形参2 ……)
函数类型 函数名(参数类型1, 参数类型2 ……)
以下情况可以不用声明
定义在前,调用在后
在所有函数定义之前,文件开头函数外已经声明了 各主调函数不用再做声明
函数返回值为int可以不用声明
函数的嵌套调用
调用另一个函数
e = 1 + 1/1! + 1/2! + 1/3! + …… 1/n!
double fun( int n )计算n的阶乘
double e( int n )计算n项和
void main()
函数的递归调用
直接递归 、间接递归
类似于函数的嵌套调用,只不过每次调用的都是同一个函数
可用递归实现的条件
初始情况(终止条件),如:n<=1
情况n能用情况n-1来描述 如: n! = n * (n-1)!
注:先测试,后递归,递归是有条件的, 满足条件才可以递归
练习
正常解题
由终止条件,反推结果
抄3遍
评价
递归可以转换为非递归
递归的实现借助于 栈
数组作为函数参数
数组元素 做 实参
与变量同级别
值传递
数组名做函数参数
数组名,地址常量
传地址
注
定义:应当在主调、被调函数中分别声明数组
类型:一致
大小:形参数组和实参数组大小可以不同 形参数组可以不指定大小, 设另一个参数传递元素个数 void fun( int array[], int n )
数组名做实参,不是把数组的值传递给形参数组 而是将实参数组的起始地址,传递给形参数组。 形参数组与实参数组共占同一段存储单元, 形参数组中的元素发生变化,影像实参数组
多维数组做函数参数
实参,用 数组名
形参,可以指定每一维的大小,可以省略第一维大小
练习
对一维数组中的前n个元素排序
将二维数组中每一列的最小元素的行号,保存在一维数组中
局部变量和全局变量
局部变量
位置
函数内
复合语句内
作用域
定义它的函数
定义它的复合语句
生存期
调用时分配存储单元,结束时释放(static除外)
说明
main函数中定义的变量,也仅在mian函数中有效
不同的函数中可以定义相同名字的变量,代表不同的对象,内存中占据不同的存储单元,互不干扰
形参也是局部变量
全局变量
位置
函数外
作用域
定义起,至文件结束 声明起,声明它的函数
生存期
静态存储区, 至程序运行结束,始终占用内存不释放
说明
作用:增加了函数间的通信渠道
建议少用
生存期
通用性
可读性
任何函数都可以修改,很难确定某一时刻变量的值
在用一个源文件中,全局变量与局部变量同名
在局部变量的作用域内,全局变量不起作用
取最近的原则
变量的存储类别
作用域、生存期
变量和函数属性
数据类型
存储类别
在内存中存储的方法
静态存储
动态存储
auto变量
函数中局部变量,不专门声明static时,默认auto
分配在动态存储区,分配释放由系统决定
作用域
定义它的函数
生存期
调用时分配,结束释放
特点
系统不能初始化,每次调用需人工赋初值
static声明的局部不变量
调用结束,不释放存储单元,保留上次调用结束的值
作用域
与局部变量相同
生存期
始终占用内存不释放
特点
系统自动赋初值,也可人工赋初值,初始化只做一次
保留上次调用结束的值
register寄存器变量
register int i,j=10;
特点
局部自动变量和形参,全局变量不行
寄存器的个数有限,不能定义太多
register static int a = 10; 错
用extern声明外部变量
在文件内声明外部变量
扩展全局变量的作用域
位置
使用它的函数中
文件开头
extern int a, b;
extern a, b;
在多个文件的程序中声明外部变量
一个文件引用另一个文件中的全局变量
位置
文件开头
静态存储区
全局变量,static声明的局部变量
系统自动赋初值,也可人工赋初值
动态存储区
局部变量(无static)
形参
每次调用人工赋初值
内部函数和外部函数
内部函数 (静态函数)
只能被本文件中的其他函数调用的函数
定义时在函数名和函数类型前加static
static int fun( int a, int b ){}
外部函数
定义时前面冠有extern,表示外部函数
函数隐含为外部函数
extern int fun( int x, inty ){}
指针
概述
直接访问
通过变量名
间接访问
通过指针表示指向的关系
一个存放地址的变量指向一个普通变量
存放地址的变量称为指针变量
注意
指针
地址
1000
指针变量
存放地址的变量
p
指针变量
定义
基类型 *指针变量名;
int *p;
定义时,*不做任何运算,说明其后面的p是一个指针变量,p指向于int,即p能够存放int变量的地址
p是指针变量,变量p中存放地址,不是*p
运算
赋值
取变量的地址
int x, *p; p = &x;
取数组的首地址
int a[10], *p; p = a; 或 p = &a[0];
指针变量相互赋值
int x, *p1, *p2; p1 = &x; p2 = p1;
p1和p2指向的类型要相同, 赋值时,右边的指针变量有确切的指向
申请空间返回地址
int *p; p = (int *)malloc( sizeof( int ) );
包含malloc.h
赋NULL值
int *p; p = NULL; p = 0; p = '\0'
使p指向为空,防止误用
初始化
存储类别 基类型 *指针变量名 = 地址;
int x, *p = &x;
算术运算
指针变量指向一段连续的存储单元 可与int完成加减,自增,自减运算
int a[10]; p1=p2-1; 想到字符的加减运算 int *p1, *p2; p2=p1+3; p1 = a; p2-p1; p2 = a + 1;
p1+p2无意义
关系运算
一段连续的空间
注意
int *p; p是指针变量,不是*p
指针变量只能指向同类型的变量
取地址运算符和指针运算符
&
运算对象,必须是已经定义的变量或数组元素
运算结果为 该变量在内存中的首地址
&3, &(x+y),寄存器变量 错
*
运算对象,已经赋值的指针,地址
作用:取给定地址所指向单元中的内容
*与&运算的互为逆运算
优先级相同,右结合
*&a => *(&a) => *(1000) => *pa => a
&*pa => &(*pa) => &(a) => 1000 => pa
&*a => a 错
注意:&变量,*地址
指针变量只能存放地址
指针变量做函数参数
指针变量做函数参数,传地址
函数在执行过程中,使指针变量所指向的变量值发生变化
指针与一维数组
变量的地址
数组的首地址:起始地址,数组名
指向数组元素的指针变量
int a[10]; int *p; p = a;或 p = &a[0];
通过指针变量引用数组元素
p=a; a[i]<=>*(a+i),中括号变址运算符 p = a + 3; p[5] = ? a[8] a:数组名,地址常量,不能修改 a++ 错 p:指针变量,可以修改 p++
第i个元素的地址&a[i]
p+i
a+i
子主题 4
第i个元素的值 a[i]
*(p+i)
*(a+i)
指针法
指向一维数组的指针也可以带下标
p[i]
a[i]
下标法