函数的定义:
格式: 类型标识符 函数名(形参表)
{
说明部分;
执行部分;
}
类型标识符: 说明了函数返回值的类型, int 可省略; void 为无返回值
函数名: 同一程序,函数名唯一;
函数名: 圆括号不可省略;
例:
定义函数: 乘方
float power (float x,int n)
{
int i;
float t=1.0;
for (i=1; i<=n; i++)
t=t*x;
return t; // return的数据与定义格式不符时,以定义为准;
}
一: 函数调用结束之后,即刻释放分配的内存单元;形参只在函数内部有效
二: 形参、实参在数量,类型上严格一致;
三: 形参只能是变量。
四: 实参和形参可以同名,但分配在不同的存储空间;
函数参数的传递:
只能由实参到形参,不能被带回:
例:
在函数中交换两个元素
void swap(int a,int b)
{
int i;
printf("a=%d,b=%d\n",a,b);
i=a;
a=b;
b=i;
printf("a=%d,b=%d\n",a,b); // 在函数中形参交换数据;
}
void main()
{
int x=6,y=9;
printf("x=%d,y=%d\n",x,y);
swap(x,y);
printf("x=%d,y=%d\n",x,y); // 在定义函数之外,实参并未变化;
}
函数的声明:
若把函数的定义放在了调用之后,需要在函数调用之前,对函数进行声明;
格式:
类型标识符 函数名(类型标识符 形参1,类型标识符 形参2,……);
分号不可省略;
函数的嵌套调用:
在一个函数中完整的包含另一个函数:
main→ 函数a(含有函数b)→ 函数b → 返回继续函数a → 结束
例:
计算 s=1^2!+2^2!+……+x^2!
编写两个函数,一个计算平方,一个计算阶乘
long f1(int p); // 函数声明;
void main()
{
int i,x;
long s=0;
printf("请输入平方阶乘和的最大一个数:\n");
scanf("%d",&x);
for (i=1; i<=x; i++) // 借助函数进行计算;
s=s+f1(i);
printf("\ns=%ld\n",s);
}
long f1(int p)
{
int k;
long r;
long f2(int);
k=p*p; // 计算乘方;并执行f2;
r=f2(k);
return r; // 输出结果;
}
long f2(int q)
{
long c=1;
int i;
for(i=1; i<=q; i++) // 计算阶乘;
c=c*i;
return c;
}
函数对它本身的调用;
例:
x(n)=x(n-1)+2; x(1)=10; 求x(5);
x(int n)
{
int c;
if(n==1)
c=10;
else
c=x(n-1)+2; // 等价于 x(5)=x(4)+2=x(3)+2+2=x(2)+2+2+2=.....
return(c);
}
void main()
{
printf("%d\n",x(5));
}
反向输出一个整数:
void main()
{
void output(int x);
int n;
scanf("%d",&n);
if(n<0) // 若输入为负数,先输出负号;
{
n=-n;
putchar('-');
}
output(n); // 执行调换函数;
printf("\n");
}
void output(int x) // 调换函数;
{
if(x>=0 && x<=9) // 如果x是个位数(仅有一位),输出x;
printf("%d",x);
else
{
printf("%d",x%10); // 分离出个位;
output(x/10); // 执行下一个数;
}
}
一:数组元素作为实参使用;与普通变量一样;
二:数组名作为实参和形参使用;
一:数组元素作为实参使用:
例:
比较两个字符串的大小
void main()
{
int i,flag; // flag为ASCII码之差,与零比大小,来判断谁大谁小;
int compchar(char ,char);
char str1[80],str2[80];
gets(str1);
gets(str2);
i=0;
do // 数组元素作为函数实参,执行比较函数;
{
flag=compchar(str1[i],str2[i]);
i++;
}
while ( (str1[i]!='\0'||str2[i]!='\0')&&(flag==0)); // 若flag不为零,直接输出结果;
// 字符串相同时,字符串若结束,再比较一次,使得flag不为零,结束循环;
if (flag==0) // 判断flag的正负来输出结果;
printf("%s = %s",str1,str2);
else if (flag>0)
printf("%s > %s",str1,str2);
else
printf("%s < %s",str1,str2);
printf("\n");
}
int compchar (char c1,char c2)
{
int t;
t=c1-c2; // 计算两个字符的差;
return t;
}
1. 形参与实参都用数组名,且实参与形参的类型、维数相同;
2. 将实参的地址传递给形参,形参与实参共用相同的存储区域;
3. 若形参数组的数据发生了变化,则主函数的实参数组也变化;
例:
利用选择排序法对数组元素由大到小进行排序;
void nzp(int a[80], int n) // 在定义数组名函数的时候,一般返回值为空,定义可多加数组长度;
{
int i,j,k,t;
for (i=0; ia[k])
k=j;
if(k!=i) // 如果最大的元素不是排序范围内的第一个元素,
{
t=a[k]; // 将最大的元素与排序的第一个元素互换;
a[k]=a[i];
a[i]=t;
}
}
}
void main()
{
int b[80],i,n;
printf("请输入要排序的数的个数:\n");
scanf("%d",&n);
printf("\n请输入数据:\n");
for(i=0; i
1. 指定一维数组中各元素的大小(列数,即一行中的元素个数);
2. 可以省去第一维的长度:
int fun(int a[][10])
但是在进行函数计算的时候,要标好行列的长度;
3. 不能省略第二维;
例:
求二维数组c每行中的最大元素,并依次放入一维数组b中:
void fun(int c[80][40],int b[40],int m,int n) // 定义二维数组的长度需要两个变量;
{
int max,i,j;
for(i=0; imax)
max=c[i][j];
b[i]=max; // 将max附给数组b;
}
}
void main()
{
int c[80][40],b[40],i,j,m,n,k;
printf("请输入将要排序的二维数组的行数与列数:\n\n"); // 标准的二维数组输入;
scanf("%d%d",&m,&n);
printf("请分别按行输入将要排序的二维数组:\n\n");
for(i=0; i
一、 局部变量(内部变量)
只能在本函数内或复合语句中使用;如形参就是局部变量;
作用域: 定义位置到他按所在的函数或复合语句结束;
1. 同一作用域内不能出现同名变量;
不同的作用域可以出现同名变量;
例:
for( int i = 0; ... ); for( int i = 0; .... ); 可以重复定义循环变量;
2. 局部变量的定义必须放在所在函数の全部可执行语句之前;
3. 当作用域发生嵌套时;以内层函数的局部变量定义为准,外层被屏蔽;
4. 主函数不能使用其他函数中定义的局部变量;
局部变量的作用域:
void prt(void);
void main()
{ // x=1作用域:
int x=1; //**
{ //**
int x=2; // x=2作用域; //**
{ //** //**
int x=3; // x=3作用域; //** //**
prt(); //** //** //**
printf("(2)x=%d\n",x); //** //** //**
} //** //**
printf("(3)x=%d\n",x); //** //**
} //**
printf("(4)x=%d\n",x); // 外层函数被内层定义屏蔽 //**
}
void prt(void)
{ // x=5作用域;
int x=5; //**
printf("(1)x=%d\n",x); //**
}
二、全局变量:
函数外部的任意位置上定义的变量;
作用域: 从变量定义的位置开始,到他所在的源文件结束为止;所有函数都能使用;
允许全局变量与局部变量同名;在局部变量的作用域内,全局变量不起作用;
int x=10; // 定义全局变量,赋值为10;
void fun(void);
void main()
{
printf("main1:%d\n",x); // 输出全局变量;
x=20; // 定义局部变量,与全局变量同名,屏蔽全局变量;
fun(); // 执行fun函数;
printf("main2:%d\n",x); // 输出局部变量x=20;
}
void fun(void) // 定义同名局部变量x,屏蔽全局变量;
{
int x;
x=30;
printf("fun:%d\n",x);
}
三、变量的存储类别:
一。变量的生存期:
变量的存储类别分为:动态类和静态类;
动态存储类别:
1. 存储在动态存储器和寄存器中;
2. 生存期从变量定义开始到函数运行结束为止;
3. 可用的定义:auto(自动);register(寄存器);
静态存储类别:
1. 存储在静态静态存储器中;
2. 生存期从程序运行开始一直延续到程序运行结束;
3. 可用的定义:static(静态);extern(外部);
一般的定义形式:
存储类别说明符 类型标识符 变量名表列; static int a;
二。局部变量的存储类别:
内部定义局部变量时,若没有指定类别,或者使用了auto,就是自动变量;
2.静态局部变量:
1. 静态局部变量生存期虽然延伸至整个程序结束,但是只能在定义该变量的函数中使用;
退出该函数后,虽然变量依然存在,但是不能使用;
2. 静态局部变量初值是在编译时赋予的;不是在程序执行时初始化的,所以只能够赋值一次;
所以初值只能是常量表达式。
3. 若定义静态变量不附初值的话,编译系统直接附初值(数值赋值0;字符赋值空字符);
4. 自动变量,编译系统不附初值;
例:
静态局部变量的使用:
void main()
{
int i;
void f1();
void f2();
for (i=1; i<=5; i++)
{
printf("第%d次循环\n",i);
f1();
f2();
printf("\n");
}
}
void f1()
{
static int j; // 静态变量定义时若不赋值,自动赋值为0;
++j; // 静态变量的定义只执行一次;所以j随循环变化;
printf("j=%d\n",j);
}
void f2()
{
int k=0;
++k; // 动态变量定义时随循环继续执行,所以k一直输出为1;
printf("k=%d\n",k);
}
三。寄存器变量:
存放在CPU寄存器之中,寄存器个数有限,虽然速度快,但是一般不使用;
且不能调用指针操作;
例:
使用寄存器变量
void main()
{
register int i,s=0;
for(i=1; i<=100; i++)
s=s+i;
printf("s=%d\n",s);
}
四。全局变量的存储类别:
全局变量(外部变量),只有静态类别,生存期是整个程序的运行期;
初始化在编译时完成,赋值只能是常量表达式;
一。extern声明全局变量:
扩展变量作用域:
1. 作用域扩展到定义之前;
2. 扩展到一个工程的其他原文件当中;
例:
F1.C的内容如下:
int x=0; // 外部变量的定义;
extern int b; // 扩展外部变量,使整个源文件可用;
void main()
{
……
……
…………
extern int a; // 扩展外部变量,使整个main函数可用;
}
void fun11()
{ …… }
int a,b,c; // fun11中不能使用全局变量a,但是可以使用全局变量b,全局变量c没有进行声明也不能使用。
void fun12()
{ …… }
F2.C的内容如下:
extern int x; // 声明外部变量,使F2.C可用F1.C中定义的外部变量x;
void fun21(int a,int b)
{ …… }
注: extern 可以在别的源文件中使用,用于扩展其他的全局变量的范围到本文件!!
二。静态外部变量:
静态外部变量不能使用extern让其它源文件调用,作用域限制在定义该变量的源文件中;
可以让其它源文件定义重名外部变量,不会引起混乱;
例:
F1.C的内容:
static int x,y;
char z;
main()
{
……
……
}
F2.C的内容:
extern int x; // 由于F1.C中定义的静态全局变量,所以在F2.C中无法引用;
extern char z; // z可以被引用;
int y; // 此处定义的y与F1.C中的y不同;(覆盖)
void func (int a,char ch)
{
x=a;
z=ch;
}
五。内部与外部函数
1. 内部函数(静态函数):
定义的函数只能在本文件中调用,
定义格式:
static 类型标识符 函数名(形参表) {函数体}
2. 外部函数:
外部函数在整个源文件中有效。
定义格式:
extern …………