函数
计算(1)+(1+2)+(1+2+3)+…+(1+2+3+4+5)
#include <stdio.h>
int sum(int n)
{
int i,s=0;
for (i=1;i<=n;i++)
s=s+i;
return s;
}
void main()
{
int s,i;
for(i=1,s=0;i<=5;i++)
s=s+sum(i);
printf("%d\n",s);
}
函数的定义和调用
类型 函数名(参数列表)
{
函数体
}
如
int sum(int n)
{
int i,s=0;
for (i=1;i<=n;i++)
s=s+i;
return s;
}
返回一般是运行结果或状态值
用return语句
return 后面跟表达式
如果是返回void 类型,用return;
例如:
1)无参函数
int sum(void)//无参函数
{
int i,s=0;
for (i=1;i<=n;i++)
s=s+i;
return s;
}
2)有参函数
int sum(int n)//有参函数
{
int i,s=0;
for (i=1;i<=n;i++)
s=s+i;
return s;
}
调用
实参和形参是一对一的关系,类型必须相同
形参(形式参数)在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参。
实参(实际参数)函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参。
形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。
实参可以是变量 常量 表达式,而形参必须是变量
传递
值传递和地址传递(指针传递)
#include <stdio.h>
void swap(int a,int b)//swap的中文是交换的意思,swap()的作
// 用是交换两个变量的值
//t是中间变量
{
int t;
t=a;
a=b;
b=t;
printf("a为%d,b为%d\n",a,b);
}
void change(int x[10])
{
int i;
for (i=0;i<10;i++)
x[i]=x[i]+1;//每个元素加一
}
void main()
{
int x=10,y=20;
int a[10]={1,2,3,4,5,6,7,8,9,10};
int i,s=0;
swap(x,y); //值传递,传递的是x,y的值
printf("x为%d,y为%d\n",x,y);
for(i=1;i<=10;i++)
s=s+a[i];
printf("s=%d\n",s);
s=0;
change(a); //地址传递,数组名a是所有数组元素的首地址
for (i=0;i<10;i++)
s=s+a[i];
printf("s=%d\n",s);//每个元素都加了1,所有s加了10
}
声明
引用性声明(是一种语句)
<类型><函数名>(<形参表>)
int sum(int a, int b);//函数名
int sum (int ,int);//形参表
作用域
就是作用范围
注意:不同作用域允许相同的变量和函数出现,而同一作用域的变量和函数不能重复。
#include <stdio.h>
int a=10; //a作用域为从定义处到文件结尾
static int add (int a ,int b) //函数为内部函数,其他文件不能调用
{
return a+b;//a,b作用域为add()
}
void main()
{
int a,b,c;//a,b,c作用域为main函数体,a将屏蔽函数外的全局变量a
int i,s=0;//i的作用域在main
int sub(int ,int );//sub 在调用之后,在此做原型声明
extern int d;//声明外部变量,因为在引用之后
a=20;
c=10;
{ //复合语句,块的一种
int a;//屏蔽了main中的a和函数外的全局变量a
int c=20;//屏蔽main中的c
b=10;//直接修改块之外的c
a=add(b,c);//直接引用add
}
printf("a=%d,b=%d,c=%d\n",a,b,c);
for (i=1;i<=100;i++)
{
s=s+i;
}
for (i=1;i<=100;i++)
{
s=sub(s,i);
}
printf("s=%d\n",s);
printf("d=%d\n",d);
}
extern int sub(int a,int b)//外部函数,其他文件可调用
{
return a-b;
}
int d=888; //全局变量,main加extern可以提前引用
int e=999; //全局变量,后面没函数,作用域实际为空
在以上函数内部和复合语句中定义的变量称为局部变量,仅在内部使用
函数外部的变量叫做全局变量,可以在所有函数和复合语句中使用
全局变量和函数可以加extern的原型声明来提前获得使用权限
extern int d;//声明外部变量,因为在引用之后
extern int sub(int a,int b)//外部函数,其他文件可调用
存储类型
一个程序的内存占用的空间分为程序区和数据区
数据区分为静态和动态数据区
程序区 | 静态数据区 |
---|---|
动态数据区 |
- 自动类型
auto用于局部变量存储类型声明,可省略。是动态变量,声明时系统不会自动初始化,值会随机赋予,所以必须在使用前初始化或赋值。
以下错误示范:
int add(int a,int b)
{
int c; //c没有初始化
c=c+a+b; //c因为没初始化,所以不能在右边表达式引用
return c;
}
auto int a; //不可以在外部变量用auto,它只可以在局部变量
- 寄存器类型
register 用于局部变量的存储类型声明,表示请求编译器尽可能直接分配使用CPU的寄存器,寄存器满了再分配内存。主要用于循环变量,提高效率,但对我而言使用的少。 - 静态类型
static放在静态储存区,全局和局部变量都可以声明为static,但意义不同:
- 全局变量总是静态存储,默认为0。加上static表示只能在本程序文件内使用
- 局部变量声明为static时要求对该变量采用静态存储的内存分配方式,只初始化一次,多次遇到该声明将不再被执行。
#include <stdio.h>
int s;
static int t; //其他文件不能用
void main()
{
int sum(int);
int i;
for(i=3;i<=5;i++)
{
s=sum(i);
t=t+s; /因为t是全局变量,初始化自动为0
}
printf("1+2+3+4+5=%d\n",s);
printf("(1+2+3)+(1+2+3+4)+(1+2+3+4+5)=%d\n",t);
}
int sum(int n)
{
static int s=0; //s是局部变量,初始化只进行一次,即该语句只进行一次
int i;
for(i=1;i<=n;i++)
s=s+i;
return s;
}
不难看出,第二个答案是错的
仔细分析代码
int sum(int n)// sum计算1+2+3.。。。+n
{
static int s=0; //s是局部变量,初始化只进行一次,即该语句只进行一次,所以在sum(4)时,s的值是sum(3)=6,
int i;
for(i=1;i<=n;i++)
s=s+i;
return s;
}
void main()
{
int sum(int);
int i;
for(i=3;i<=5;i++)//for循环三次调用sum
{
s=sum(i);//s最后值是sum(5)
t=t+s; /因为t是全局变量,初始化自动为0
//t三次结果累加
}
printf("1+2+3+4+5=%d\n",s);
//事实上t=sum(3)+(sum(3)+sum(4))+(sum(3)+sum(4)+sum(5))=6+(6+10)+(6+10+15)
printf("(1+2+3)+(1+2+3+4)+(1+2+3+4+5)=%d\n",t);//而这题答案应该是31
}
这样改:将static s=0 改成int s=0
代码如下:
#include <stdio.h>
int s;
static int t; //其他文件不能用
void main()
{
int sum(int);
int i;
for(i=3;i<=5;i++)
{
s=sum(i);
t=t+s; //因为t是全局变量,初始化自动为0
}
printf("1+2+3+4+5=%d\n",s);
printf("(1+2+3)+(1+2+3+4)+(1+2+3+4+5)=%d\n",t);
}
int sum(int n)
{
/*static*/ int s=0; //s是局部变量,初始化只进行一次,即该语句只进行一次
int i;
for(i=1;i<=n;i++)
s=s+i;
return s;
}
- 外部类型
extern用于外部的连接。
对于全局变量,extern int a和int a 效果一样
递归请看另一篇文章