7.1函数的定义和使用
7.1.1初见函数
#include<stdio.h>
int main4()
{
int count=0;
for(int x=2;count<50;x++)
{
int isPream=1;
for(int i=2;i<x;i++)
{
if(x%i==0)
{
isPream=0;
}
}
if(isPream==1)
{
count++;
printf("%d\t",x);
if(count%5==0)
{
printf("\n");
}
}
}
return 0;
}
在素数求和代码中for循环使我们的代码看起来很累赘,所以我们可以将它封装为一个函数,供我们调用,代码如下:
int isPrime(int i)
{
int ret = 1;
int k;
for (k = 2;k<i-1;k++)
{
if(i%k==0)
{
ret = 0;
break;
}
}
return ret;
}
求和代码:
#include<stdio.h>
int main()
{
int start;//求和的起始值
int end;//求和的终止值
printf("请输入求和的起始值和终止值:\n");
scanf("%d %d",&start,&end);
int sum=Add(start,end);//调用求和函数,将结果保存到sum中
printf("%d到%d之间的整数和为%d\n",start,end,sum);//输出结果
}
int Add(int start,int end)//求起始整数到终止整数之间整数的和
{
int sum=0;//求和的结果
for(int i=start;i<=end;i++)//循环求和
{
sum+=i;//求和
}
return sum;//返回求和的结果
}
这里的Add也是函数,可以将重复的代码写成一个函数,减少代码的累赘。
==代码复制是程序质量不良的表现==
7.1.2函数的定义和调用
什么是函数?
函数是一块代码,接收零个或多个参数,做一件事情,并返回零个或一个值
可以先想象成数学中的函数:
y=f(x)
函数的定义
调用函数
函数名(参数值);
()起到了表示函数调用的重要作用
即使没有参数也需要()
如果有参数,则需要给出正确的数量和顺序
这些值会被按照顺序依次用来初始化函数中的参数
函数返回
void sum(int begin,int end)
{
int i;
int sum=0;
for(i=begin;i<=end;i++)
{
sum+=i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}
函数知到每一次是哪里调用它,会返回到正确的地方
7.1.3从函数中返回值
int max(int a,int b)
{
int ret;
if(a>b)
{
ret=a;
}
else
{
ret=b;
}
return ret;
}
return停止函数的执行,并送回一个值 return; return 表达式; 一个函数里可以出现多个return语句 从函数中返回
int a,b,c;
a=5;
b=6;
c=max(10,12);
c=max(a,b);
c=max(c,23);
c=max(max(c,a),5);
printf("%d",max(a,b));
max(12,13);
可以赋值给变量 可以再传给函数 甚至可以丢弃 有的时候要的是副作用 没有返回值的函数 void 函数名(参数表) 不能使用带值的return 可以没有return 调用的时候不能做返回值的赋值 ==如果函数有返回值,则必须使用带值的return==\
7.2函数的参数和变量
7.2.1函数原型:用来告诉编译器这个函数长什么样儿
函数先后关系
#include<stdio.h>
void sum(int begin,int end)
{
int i;
int sum=0;
for(i=begin;i<=end;i++)
{
sum+=i;
}
printf("sum = %d\n",sum);
}
int main()
{
sum(1,10);
sum(20,30);
sum(35,45);
return 0;
}
像这样吧sum()写在上面,是因为: C的编译器自上而下顺序分析你的代码 在看到sum(1,10)的时候,它需要知道sum()的样子 也就是sum()要几个参数,每个参数的类型如何,返回什么类型 这样它才能检查你对sum()的调用是否正确 函数原型 函数头,以分号;结尾,就构成了函数的原型 函数原型的目的是告诉编译器这个函数长什么样 名称 参数 返回类型 旧标准习惯把函数原型写在调用它的函数里面 现在一般写在调用它的函数前面 原型里可以不写参数的名字,但是一般仍然写上
7.2.2参数传递
调用函数 如果函数有参数,调用函数时必须传递给它数量,类型正确的值 可以传递给函数的值是表达式的结果,这包括: 字面量 变量 函数的返回值 计算的结果 类型不匹配 调用函数时给的值与参数的类型不匹配时C语言传统上最大的漏洞 编译器总是悄悄替你把类型转换好,但是这很可能不是你所期望的 后序的语言,C++/Java在这方面很严格 传过去的是什么? ==C语言在调用函数时,永远只能传值给函数==
#include <stdio.h>
int sum(int a,int b)
{
int t=0;
t=a;
a=b;
b=t;
return a,b;
}
int main()
{
int a=1;
int b=3;
sum(a,b);
printf("%d,%d",a,b);
}
这样的代码是不可以将a和b的值替换 传值 每个函数有自己的变量空间,参数也位于这个独立的空间中,和其他函数没有关系 过去,对于函数参数表中的参数,叫做“形式参数”,调用函数时给的值,叫做“实际参数” 由于容易让初学者误会实际参数就是实际在函数中进行计算的参数,误会调用函数的时候把变量而不是值传进去了,所以我们不建议继续用这种古老的方式来称呼它们 我们认为,它们是参数和值的关系
7.2.3本地变量定义在函数内部的变量是本地变量,参数也是本地变量
本地变量 函数的每次运行,就产生了一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量 定义在函数内部的变量就是本地变量 参数也是本地变量 变量的生存期和作用域 生存期:什么时候这个变量开始出现了,到什么时候它消亡了 作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以起作用) 对于本地变量,这两个问题的答案是统一的:大括号内--块 本地变量的规则 本地变量是定义在块内的 它可以是定义在函数的块内 也可以定义在语句的块内 甚至可以随便拉一对大括号来定义变量 程序运行进入这个块之前,其中的变量不存在,离开这个块,其中的变量就消失了 块外面定义的变量在里面仍然有效 块里面定义了和外面同名的变量则掩盖了外面的 不能在一个块内定义同名变量 本地变量不会被默认初始换 参数在进入函数的时候被初始化了
7.2.4 函数庶事:一些关于函数的细节问题,main()是什么
没有参数时 void f(void); 还是 void f(); 在传统C中,它表示f函数的参数表未知,并不表示没有参数 逗号运算符? 调用函数时的逗号和逗号运算符怎么区分? 调用函数时的圆括号里面的逗号是标点符号,不是运算符 函数里的函数? C语言不允许函数嵌套定义 关于main int main()也是一个函数 要不要写成 int main(void)? return的0也可以被输出