7.1函数的定义与使用
#include
intmain() {
intm,n;
intsum=0;
intcnt=0;
inti;
scanf("%d %d",&m, &n);
// m=10,n=31;
if(m==1) m=2;
for(i=m; i<=n; i++){
intisPrime=1;
intk;
for(k=2; k<i-1; k++){
if(i%k==0){
isPrime=0;
break;
}
}
if(isPrime){
sum+=i;
cnt++;
}
}
printf("%d %d\n", cnt, sum);
return0;
}
// 把这段代码取出来
intisPrime=1;
intk;
for(k=2; k<i-1; k++){
if(i%k==0){
isPrime=0;
break;
}
}
#include
//求1到10、20到30和35到45的三个和
voidsum(intbegin,intend)
{
inti;
intsum=0;
for( i=begin;i<=end; i++){
sum+=i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}
intmain()
{
sum(1,10);
sum(20,30);
sum(35,40);
return0;
}
什么是函数?
- 函数是一块代码,接收零个或者多个参数,做一件事情,并返回零个或一个值
- 可以先想像成数学中的函数:y=f(x)
函数定义
调用函数
- 函数名(参数值);
- ()起到了表示函数调用的重要性,即使没有参数也需要()
- 如果有参数,则需要给出正确的数量和顺序
- 这些值会被按顺序依次用来初始化函数中的参数
函数返回
函数知道每一次是在哪里调用它,会返回到正确的地方
从函数中返回值
- return停止函数的执行,并送回一个值
- return;
- return 表达式;
- 一个函数里可以出现多个return语句
- 例如:int c, c = max(10,12);=>可以赋值给变量或者再传递给函数甚至可以丢弃,有的时候要的是副作用
没有返回值的函数
- void 函数名(参数表)
- 不能使用带值的return
- 可以没有return
- 调用的时候不能做返回值的赋值
- 如果函数有返回值则必须使用带值的return
7.2函数的参数和变量
函数原型
函数的先后关系
#include
voidsum(intbegin,intend)
{
inti;
intsum=0;
for( i=begin; i<=end; i++){
sum+=i;
}
printf("%d到%d的和是%d\n",begin,end)
}
intmain()
{
sum(1,10);
sum(20,30);
sum(35,45);
return0;
}
- 像这样把sum()写在上面,是因为:c的编译器自上而下顺序分析你的代码
- 在看到sum(1,10)的时候,它需要知道sum()的样子
- 也就是sum()要几个参数,每个参数的类型如何,返回什么类型。这样它才能检查你对sum()的调用是否正确
此函数原型
#include
doublemax(doublea,doubleb) => 这是函数原型
intmain()
{
inta,b,c;
a=5;
b=6;
c=max(10,12); =>这中间一段是根据原型判断
printf("%d\n",c);
max(12,13);
return0;
}
doublemax(doublea, doubleb) =>这是实际的函数头
- 函数头:以分号“;”结尾,就构成了函数的原型
- 函数原型的目的是告诉编译器这个函数长什么样子:名称、参数(数量及类型)、返回类型
- 旧标准习惯把函数原型写在调用它的函数里面
- 现在一般写在调用它的函数前面
- 原型里可以不写参数的名字,但是一般仍然写上
参数传递
调用函数
- 如果函数有参数,调用函数的时候必须传递给它数量、类型正确的值
- 可以传递给函数的值是表达式的结果,这包括:字面量、变量、函数的返回值、计算的结果
inta,b,c;
a=5;
b=6;
c=max(10,12);
c=max(a,b);
c=max(c,23);
c=max(max(23,45),a);
c=max(23+45,b);
类型不匹配
- 调用函数时给的值与参数的类型不匹配是C语言传统上最大的漏洞
- 编译器总是悄悄替你把类型转换好,但是这很可能不是你所期望的
- 后续的语言,C++/java在这方面很严格
C语言在调用函数时,永远只能传值给函数
#include
voidswap(inta,intb); //这是参数
intmain()
{
inta=5;
intb=6;
swap(a,b); //这是值
printf("a = %d b = %d\n",a,b);
return0;
}
voidswap(inta,intb) //参数
{
intt=a;
a=b;
b=t;
}
传值
- 每个函数有自己的变量空间,参数也位于这个独立的空间中,和其他函数没有关系
- 过去,对于函数参数表中的参数,叫做"形式参数",调用函数时给的值叫做"实际参数"(实参与形参)
- 由于容易让初学者误会实际参数就是实际在函数中进行计算的参数,误会调用函数的时候把变量而不是值传进去,所以我们不建议继续使用这种古老的方式来称呼它
- 我们认为,它们是参数和值的关系
本地变量
- 函数的每次运行,就会产生一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量
- 定义在函数内部的变量就是本地变量
- 参数也是本地变量
变量的生存期和作用域
- 生存期:什么时候这个变量开始出现了,到什么时候它消亡了
- 作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以起作用)
- 对于本地变量,这两个问题的答案是统一的:大括号内——块
本地变量的规则
1.本地变量是定义在块内的
- 它可以是定义在函数的块内
- 也可以定义在语句的块内
- 甚至可以随便拉一对大括号来定义变量
2.程序运行进入这个块之前,其中的变量不存在,离开这个块,其中的变量就消失了
3.块外面定义的变量在里面仍然有效
4.块里面定义了和外面同名的变量则覆盖了外面的变量(块内的变量优先度更高)
5.不能在一个块内定义同名的变量
6.本地变量不会被默认初始化
7.参数在进入函数的时候被初始化了
其他细节
没有参数时
- void f(void)还是void f();
- 在传统C中,它表示f函数的参数表示未知,并不表示没有参数
逗号运算符?
- 调用函数时的逗号跟逗号运算符字母区分?
- 如下 => 调用函数时的圆括号内的逗号是标点符号,不是运算符
- 逗号:f(a,b) 逗号运算符:f((a,b))
函数里的函数?
C语言不允许函数嵌套定义
这是什么?
- int i,j,sum(int a,int b); //可以这样写但是不建议
- return(i); //加不加括号其实都无所谓,值都一样的,但加上括号会让人误以为这是一个函数,不要这样写没有好处
关于main
- int main()也是一个函数
- 要不要写成int main(void)? //void加不加都一样,但如果上面参数都不打算加,不妨把void写下去
- return的0有人看吗? //是可以看的起作用的,返回0表示正常的运行结束了,返回任何非0的值都是错误的
windows:if error level 1...
Unix Bash:echo $?
Csh:echo $status