c语言学习笔记——第四章:函数

第四章 函数(function)

函数可以把重复的过程精简,减少代码量。可以粗略的理解为将某一项功能打包起来。

4.1 结构化程序设计

一、结构化程序设计原则

一句话:高内聚,低耦合

关于内聚: 更具专业的来讲内聚,应该是说功能内聚,具有相同功能的接口内聚,比如,在实际开发中,项目组后端开发,有的开发A模块,有的开发B模块,而开发A,B模块都不会涉及到前台技术,开发A,B模块的人就可以理解为内聚的,而前端组开发前台页面,思考如何展示数据,后台处理数据,以及数据入库CRUD,那么此时前后台人员分工合作,中间通过暴露接口通信,那么耦合结合着对于类似的前端和后台来说, 前后端分离就是为了降低耦合度
比如一个商城系统,其中订单系统和库存系统来说,二者存在的关系是订单如果增加,库存会随之减少,但二者如果放到一个模块中,除了开发不规范之外,二者的功能中会出现较高的耦合度,所以二者就需要通过暴露接口,来处理彼此之间的数据转换,这样就是降低耦合,即低耦合,那么在开发中,订单模块涵盖的功能集中针对订单的处理,功能协作度高,那么这个就是所谓的内聚了,即聚拢相关度高的功能,功能具有针对性.
更多内容请参看「低耦合,高内聚」真的好吗?

二、模块与函数

函数体现结构化的设计思想

三、c源程序结构

  1. 组成:
    一个main(),加上n个其他function
  2. 函数定义不可以嵌套,调用可嵌套,函数也可以互相调用,但不能调用main()
  3. 函数的分类:
    • 用户角度
      1. 系统函数
      2. 用户自定义函数
    • 参数角度
      1. 有参函数
      2. 无参函数

4.2 函数的定义

把一段计算定义成函数,给以命名,定义后就可以在任何需要的地方调用
<stdio.h>就是封装好的函数库,在代码里include,后面就可以使用printf,scanf等函数
这个例子并不严谨,仅帮助理解

一、定义格式

一个函数包含函数头和函数体,具体细节如下

return_type function_name( parameter list )//第一行称为函数头
{
   body of the function              //函数体,通常需要返回数据
   return (value)
}

二、格式说明

  1. 函数头包括
    • return_type返回值
    • function_name函数名
    • perameter list参数表
      1. 函数可以有0个或多个参数,称为形式参数。形式参数之间用连接
      2. 每个参数必须指明参数类型和参数名称
      3. 形式参数为局部变量1
      4. 形参的值由调用者传入(参数传递)
  2. 函数体
    实现功能的计算代码,通常要有return

你不给也不能把你怎么样(雾)

注意
在定义函数时,需要分别定义形参的类型
int funtion1 (int a,int b)int funtion1 (int a, b)是错误的。

例子

#include<stdio.h>
#include<math.h>

int area (int a,int b)//求面积函数
{   
    int s;
    s=a*b;
    return s;//或直接写成 return s=a*b;
}
int sushu (int a)//判断一个数是否是素数,是返回1,否则返回0
{
    int k,i;
    k=sqrt(a);
    for(i=2;i<=k;i++)
    {
        if(a%i==0)
            break;
    }
    if(i>k)
        return 1;
    else
        return 0;
}
int jieceng(long a)//计算阶乘
{
    long i=1,s=1;
    for(i;i<=a;i++)
    {
        s=s*i;
    }
    return s;
}
main()
{
    printf("%d",sushu(11));//函数调用
    printf("%d",jieceng(5));
}

三、函数返回值return

  1. 格式
    return 表达式return(表达式)
  2. 返回值数量
    • 返回值最多一个
    • 可以有多条return,但只会执行一条
  3. 函数返回值与函数返回值类型的关联
    • 若函数有return,则必有返回值的类型,并且类型相同
    • 若函数有return,但没有规定返回值类型,系统自动为int
    • 若函数没有return,必须写void

结论:return_type的优先级大于return(表达式)

4.3 函数的调用

一、函数调用的格式

  1. 格式:函数名(实参列表)
  2. 执行流程:
  3. 说明
    • 主调函数:main()
    • 被调函数:用户自定义函数

二、函数调用方法

  1. 函数有返回值:表达式调用
  2. 函数无返回值:语句调用
    例:语句调用
   void prt1()
   {  printf("**************\n");   }
   void prt2()
   {  printf("I'm happy\n");        }
   main()
   {  prt1();prt2();prt1();         }

结果:
在这里插入图片描述

三、函数调用的特殊说明–函数原型

先定义,后使用

  1. 格式:
return_type function_name( parameter list );

parameter list可以只写形参类型
例:

int jieceng(long);

main()
{
    printf("%d",jieceng(9));
}

int jieceng(long a)
{
    long i=1,s=1;
    for(i;i<=a;i++)
        s=s*i;
    return s;
}
  1. 特殊情况
    • 当函数定义在上,调用在下可以不写
    • 返回值类型为int,可以不写

四、参数传递

  1. 概念
    • 形参:被调用函数中的变量
    • 实参:
    • 参数传递:实参向形参进行单向值传递。形参的改变不影响实参
  2. 参数传递机制:
    1. 内存中:形参被调时,分配空间,调用结束时,释放空间
    2. 名字上:形参与实参可以同名。
    3. 形参可为变量;实参可为变量或常量。
    4. 三个一致:个数,类型,顺序。
    5. 在自定义函数中
    • 输入集<===>形参列表
    • 输出集<===>return

void swap (int a, int b)
{
   int t;
   t=a;  a=b;  b=t;
}
int main()
{
   int a=5, b=3;
   printf("before swap a=%d, b=%d",a, b);
   swap(a,b);
   printf("after swap a=%d, b=%d",a, b);
}

两次结果均为5,3

4.4 变量的作用域与存储属性

一、变量的作用域

变量的作用域即变量的作用范围。
根据变量的位置,产生了局部变量与全局变量。

  1. 局部变量(Local Variable)
    • 定义位置:函数体内
    • 作用域:定义函数可用
    • 说明
      • 复合语句中的局部变量只能在符合语句中可用
      • 主函数不特殊(该咋地咋地)
      • 不同函数中,局部变量可以同名
  2. 全局变量(Global Variable)
    • 定义位置:函数体外。
    • 作用域:定义的位置到文件尾部。
    • 说明
      • extern可扩展全局变量作用域
  3. 同名问题:全局变量和局部变量同时出现时,局部变量优先。
#include<stdio.h>
int a = 5;
void fun (int b)
{
    int a = 10;
    a += b;          //此a为局部变量
    printf("%d\n", a);
}
main()
{
    int c = 20;
    fun(c);
    a += c;          //此a全局变量的a,更改的是全局变量。
    printf("%d\n", a);
}

二、变量的存储属性

  • 以静态形式存储的有:静态变量,全局变量
  • 以动态形式存储的有:形参,自动变量,函数调用的堆栈与返回地址时。

详情参看链接:动态存储区、静态存储区、堆和栈的区别

共有auto, static, register, extern四种存储类型。

  1. 局部变量存储属性
    1. auto:自动局部变量,在动态区开辟内存,auto可省略。
      例:auto int a=int a
    2. register:寄存器变量,存储在CPU中的寄存器中。1
      说明:
      • 数量有限
      • 只能register int a;register char a;
    3. static静态局部变量,在静态区开辟内存。
      说明:
      • static定义的局部变量未经初始化,初值为0.
      • 只在第一次初始化。
      • 只在函数内部使用,整个运行周期空间不释放。
  2. 全局变量存储属性
    可放static, extern
    静态局部变量static的举例:
#include<stdio.h>
int fun(int x)
{
    static int y;
    int z = 1;
    z += 2;
    y += x + z;
    return y;
}
main()
{
    int k;
    for(k=1; k<=3; k++)
    {
        printf("%3d",fun(k));
    }
}

在这里插入图片描述
在这里插入图片描述

图一为第一次fun执行完第二次开始时各个变量的值
图二为第二次fun执行完第三次开始时各个变量的值

总结:

存储类型作用域初始化生命周期
auto局部变量随机数
register局部变量随机数
static局部变量,全局变量0长(连续性)
extern全局变量0

  1. 详情参看寄存器 ↩︎ ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值