C语言学习笔记(12)——函数基础

目录

12.1 函数概述

12.1.1 函数的概念及作用

12.1.2 函数的分类

12.1.3 函数举例

12.2 函数的定义

12.2.1 函数定义的一般形式

12.2.2 函数定义的说明

12.2.3  函数定义举例

12.3 函数的调用

12.3.1 函数原型和函数声明

12.3.2 函数调用的一般形式

12.3.3 函数调用的三种情况

12.4 函数值和return命令

12.5 变量的作用域与存储类型

12.5.1 变量的作用域

12.5.2 变量的存储类型


12.1 函数概述

12.1.1 函数的概念及作用

  • 函数化结构是C语言程序的重要特征
  • 使用函数,能提高程序设计效率
  • 缩短程序代码,使程序简练紧凑

12.1.2 函数的分类

  • 标准库函数
  • 用户自定义函数

12.1.3 函数举例

a!+b!+c!的值。程序如下:

  • 程序结构只有main()函数的阶乘程序

程序缺点:求阶乘程序段重复三遍,结构不紧凑

void main( )
{
 int a,b,c,i;
 long t,sum;
 printf("input a,b,c:");
 scanf("%d,%d,%d",&a,&b,&c);
 for(t=1,i=1;i<=a;i++)
    t=t*i;
 sum=t;
 for(t=1,i=1;i<=b;i++)
    t=t*i;
 sum+=t;
 for(t=1,i=1;i<=c;i++)
    t=t*i;
 sum+=t;
 printf("SUM=%ld\n",sum);
}
  • 使用用户函数的阶乘程序

引入求阶乘函数rfact(),将程序优化为:

long rfact(int n)
{
 long t;
 int i;
 for(t=1,i=1;i<=n;i++)
 t*=i;
 return(t);
}

void main()
{
 long rfact(int n);
 int a,b,c,i;
 printf("input a,b,c:");
 scanf("%d,%d,%d",&a,&b,&c);
 printf("SUM=%ld\n",
 rfact(a)+rfact(b)+rfact(c));
}

12.2 函数的定义

12.2.1 函数定义的一般形式

函数定义是指在程序中编写具有特定功能的用户函数。函数定义的一般格式如下:

函数类型  函数名(形式参数表)

{

        函数体

}

12.2.2 函数定义的说明

  • 函数名是对函数的标识,是符合标识符命名规则的任何合法标识符。
  • 形式参数表是用逗号分隔的一组变量说明,其格式为:数据类型1 形参1,数据类型2 形参2,……,数据类型n 形参n
  • 函数体是实现函数功能的全部语句。
  • 函数类型:当函数有具体返回值时,为函数值的数据类型;当函数没有具体的返回值时,函数类型为void型。
  • 当函数不需要参数时,形参变量表用void填充。有的C语言系统,在定义无参数函数时允许形参表为空,但函数名后面的括号()不能省略。

12.2.3  函数定义举例

输出两个实数中的最大数。程序如下:

//定义1
float rmax2(float x,float y)
{
 float m;
 m=x>y?x:y;
 return(m);
}
//定义2
float rmax2(float x,float y)
{
 if(x>y)
     return(x);
  else
     return(y);
}
//定义3
float rmax2(float x,float y)
{
 return(x>y?x:y);
}

求和函数sum(),计算1+2+3++n-1+n的值。程序如下:

int sum(int n)
{
 int s,i;
 for(s=0,i=1;i<=n;i++)
     s+=i;
 return(s);
}

12.3 函数的调用

12.3.1 函数原型和函数声明

  • 函数原型

函数原型就是对已经定义的函数的概要描述,是定义函数时函数体以外的那些内容。一般形式如下:

  函数类型  函数名(数据类型1 形参1,数据类型2 形参2,…,数据类型n 形参n);

函数原型中对形参表进行描述时,允许省略所有形参的名称,只保留各个形参的类型说明,但它们个数和顺序完全一致。函数原型的简化形式如下:

  函数类型  函数名(数据类型1, 数据类型2,  … ,  数据类型n)

  • 函数声明

在进行函数调用之前,需对被调用函数进行函数声明。函数声明有多方面的作用,其中之一是编译程序利用函数声明对函数调用的合法性进行检查,凡是与函数原型不匹配的函数调用一律视为非法调用

函数声明可以在主调函数中进行,也可以在程序开始集中进行(也就是在函数外声明,声明语句与main函数同级)。若采用后一种形式,则在主调函数中对被调用函数的声明即可省略。

12.3.2 函数调用的一般形式

函数调用是指对已定义函数的具体应用。函数调用的一般形式如下:

        函数名(实参表)

发生函数调用时,函数中的形参将得到实参表中的数据,然后执行函数体语句,实现函数功能。

进行函数调用时,需注意以下事项:

  • 函数调用的实参个数必须与形参个数相同。
  • 实参与形参按照在参数表中的位置一一对应传值,实参与形参的名称是否相同对调用传值无任何影响。 
  • 实参与形参对应位置上的数据类型应该一致。
  • 对于无参数函数,即形参表为void的函数,函数调用时实参表必须为空,不能有任何内容。

12.3.3 函数调用的三种情况

(1)函数调用以语句的方式出现,通常只完成一种操作,不带回返回值。例如,调用例9-4的p_star()函数,输出20个连续“*”字符:

void p_star(int n)
{
    int i;
    for(i=1;i<=n;i++)
    printf("%c",'*');
}

void main()
{
    void p_star(int);  /* 函数声明*/
    p_star(20);        /* 函数调用*/
}

(2)函数调用出现在表达式中,是表达式的一部分。例如,调用例9-3定义的求和函数sum(),计算如下表达式的值:

程序代码如下:

int sum(int n)
{
    int s,i;
    for(s=0,i=1;i<=n;i++)
    s+=i;
    return(s);
}

void main()
{
    int sum(int);      /* 声明sum()函数 */
    int s;
    s=sum(20)+sum(50); /* 两次调用sum()函数 */
    printf("SUM=%d\n",s);
}

(3)函数调用作为一个函数的实参。例如,调用例9-2定义的求两个实数的最大数rmax2(),求三个数的最大数:

float rmax2(float x,float y)
{
    return(x>y?x:y);
}

void main()
{
    float rmax2(float,float); /* 声明rmax2()函数 */
    float a,b,c,max;
    scanf("%f,%f,%f",&a,&b,&c);
    max=rmax2(rmax2(a,b),c);
    printf("Max=%f\n",max);
}

12.4 函数值和return命令

函数值是函数执行后带回的一个结果,通常称为函数的返回值。

用户函数的返回值通过函数体中的return命令获得。其一般格式如下:

        return 表达式

return命令将“表达式”的值作为函数的返回值,同时结束函数运行,返回到调用它的上层函数位置。

关于return命令的说明如下:

(1)return命令也可以使用如下格式:

        return (表达式)

(2)在一个函数中允许有多个return命令,执行到任何一个return命令都将返回到主调函数。

(3)当函数不需要具体的返回值时,函数体中的return命令不使用参数(实际上,当return命令省略参数时,return语句也就可有可无了。缺少return语句的函数,执行完最后一个语句后自动返回)


12.5 变量的作用域与存储类型

12.5.1 变量的作用域

  • 局部变量

局部变量也称内部变量,其相关说明如下:

(1)在函数体内定义;

(2)只能在定义它的函数中使用;

(3)在一个程序的不同函数中可以定义同名的变量;

(4)函数的形参变量和在函数体内定义的变量都是局部变量;

(5)函数执行结束后形参变量立即消失;

(6)在函数体内定义的局部变量是否随函数结束而消失,要取决于变量的存储类型。

局部变量示例程序如下:

#include <stdio.h>
void prn_1(int);   /* 函数声明 */
void prn_2();      /* 函数声明 */

void main()
{
    int i;  /* 定义局部变量i ,它仅在main()函数内有效 */
    for(i=0;i<10;i+=5)
    {
        prn_1(i);      /* 用变量i作实参进行函数调用 */
        prn_2(); 
    }
}

void prn_1(int n) /* 输出整数值的函数 */
{
    int i; /* 定义局部变量i,它仅在prn_1()函数内有效 */
    for(i=1;i<=5;i++)
        printf("%5d",n+i);
    printf("\n");
    return;
}

void prn_2()  /* 输出一条横线的函数 */
{
    int i;          /* 定义局部变量i,它仅在prn_2()函数内有效*/
    for(i=1;i<30;i++)
        printf("%c",'-');
    printf("\n");
    return;
}
  • 局变量

全局变量的相关说明如下:

(1)在程序的任何一个函数体外定义。

(2)在一个程序中,凡是在全局变量之后定义的函数,都可以使用在其之前定义的全局变量。

(3)一个全局变量,可以被多个函数使用, 但并不一定能被所在程序中的每一个函数使用。

(4)全局变量也有一定的作用范围。

全局变量示例程序如下:

int a=3,b=5;     /* 定义全局变量 */

max(int a,int b)
{
    return(a>b?a:b); /* a、b是形参 */
}

void main()
{
    int a=8;      /* 定义局部变量 */
    printf("MAX=%d\n",max(a,b)); /* a是局部变量,b是全局变量 */
}

12.5.2 变量的存储类型

数据类型和存储类型是C语言中变量的两种不同属性,数据类型规定了变量能存储哪一类数据,存储类型则规定了变量在计算机中怎样存储。C语言变量的存储类型有3种,即auto型、static型和register型。现介绍最常用的两种。

  • auto型变量

 auto型变量通常称为自动变量

只有函数的局部变量才能定义为auto型。

auto型变量在函数被调用时为其分配存储空间,存储于内存的动态存储区,函数执行结束时存储空间自动释放。即:auto型变量随函数的调用而产生,随函数的执行结束而消失。

每次进行函数调用时,相关的auto型变量都被初始化。

auto型变量的定义形式为:auto 数据类型 变量;

在定义局部变量时,如果缺省存储类型项,则系统默认为存储类型是auto型。     

  • static型变量

static型变量通常称为静态变量,它存放在内存的静态存储区,在编译时分配存储空间,并进行初始化。

对于没有赋初值的static型变量,编译系统会自动为数值型的变量赋0值,为字符型的变量赋空值\0

静态变量定义的形式为: static 类型标识符 变量名;

在函数内定义的静态变量称为静态局部变量,在函数外定义的静态变量成为静态全局变量。

static型局部变量并不因函数运行结束而消失,而是始终存在,当再次进入该函数时, 将保留上次的结果。但无论在什么情况下,都不能被其他函数使用。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆毛小叮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值