C语言(函数)

一、函数的概念

1、在程序设计过程中,为了实现某个功能需要编写多行代码,例如求一个二维数组中的最大值,如 果该功能需要被多次使用,我们可以在每次使用时将原来的代码重复编写,但是这样未免有“凑代 码”的嫌疑,而且编程效率也不高。为了避免重复劳动,我们可以将这部分代码封装到一个“函数” 中,在需要使用该功能时调用封装好的函数即可。

#include <stdio.h>

//Array_max是函数名,()内的int a[]是需要操作的数组,int len是数组的长度
int Array_max(int a[],int len)
{
	int i;
	int max;
	
	max = a[0];
	for(i=1;i<len;i++)
	{
		if(a[i] > max)
		{
			max = a[i];
		}
	}
	
	return max;
}

int Array_min(int a[],int len)
{
	int i;
	int min;
	min = a[0];
	
	for(i=1;i<len;i++)
	{
		if(a[i] < min)
		{
			min = a[i];
		}
	}
	
	return min;
}

int main()
{
	int a[4] = {11,22,33,44};
	int max;
	int min;
	
	max = Array_max(a,4); //调用函数
	min = Array_min(a,4);
	
	printf("最大的数是:%d\n",max);
	printf("最小的数是:%d\n",min);	
	
	return 0;
}

2、函数就是具有特殊功能的指令的集合

3、C程序是由函数组成的,函数是C程序的基本模块,C程序从主函数main()开始执行

4、从函数定义的角度出发,函数可以分为库函数和用户自定义函数两种

(1)库函数:由标准C库提供,用户不需要自己实现,在使用时直接调用即可,例如printf、scanf函 数等。

(2)用户自定义函数:需要用户自己根据实际需求自己实现,例如比较两个整数的大小,并且求出最 大值。

二、函数的定义

1、函数定义的语法规则

类型标识符 函数名(形参列表)

{

        函数体

}

说明: 

1)类型标识符:函数返回数据的类型,支持C语言所有的数据类型

2)函数名:由用户定义的标识符

3)形参列表:函数用来接收用户所传递数据的参数,参数可以时0个也可以是多个

4)函数体:实现函数功能的代码块

2、无参函数的定义

(1)函数不需要接收用户传递的数据

        语法:

        类型标识符 函数名()

        {

                函数体

        }

注意:形参列表为空

 (2)如果函数不需要返回值,“类型标识符”可以设计为void

        void func()

        {        

                printf("hello world\n");

        }

 (3)如果函数需要返回值,返回值是什么类型”类型标识符“就是什么类型,例如:设计一个函数返回1~100的和。

        int func()

         {

                 int i, sum = 0;

                 for (i = 1; i <= 100; i++) sum += i;

                 return sum;

          }

/*
	设计一个函数返回0-100的和
*/
#include <stdio.h>

int func()
{
	int i;
	int sum;
	
	for(i=1;i<=100;i++)
	{
		sum += i;
	}
	printf("%d",sum);
	
	return sum;
}

int main()
{
	int j;
	func(j);
	return 0;
}

3、有参函数的定义

(1) 可以根据实际需求设计函数的形参,形参的作用就是接收用户传递的数据

          语法:

          类型标识符 函数名(类型标识符 形参1, 类型标识符 形参2 ... )

          {       

                  函数体

          }

(2) 设计一个函数计算两个整数的和

           void sum(int a, int b)

           {

                 int c = a+b;

                 printf("sum: %d\n", c);

           }

/*
	设计一个函数计算两个整数之和
*/
#include <stdio.h>

void sum(int a,int b)
{
	int c = a+b;
	printf("sum:%d\n",c);
}

int main()
{
	int a;
	int b;
	printf("请输入两个整数\n");
	scanf("%d %d",&a,&b);
	sum(a,b);
	
	return 0;
}

三、函数的参数和返回值

1、函数的形参和实参

(1)形参出现在函数的定义中,在整个函数体中都可以访问到,离开了该函数就不能被访问了
(2)实参出现在函数调用时
(3)函数调用时,将实参的值的赋值给形参
(4)形参和实参有如下特点:
         1、形参只有在函数被调用时才会被分配内存空间
         2、 实参可以是 常量、变量、表达式、函数名

 2、函数的返回值

(1)函数的返回值是函数将函数体中的执行结果返回(传递)给函数的调用者,通过return语句返回。

(2)函数执行完return后,函数退出

(3)函数的返回类型就是函数的类型

(4)如果函数不需要返回值,函数的返回类型为void,在函数体中可以使用“return“退出函数也可以不使用return

(5)如果函数返回的类型和return语句中表达式的值的数据类型不一致,则以函数返回类型为准,即 函数返回类型决定返回值的类型。对数值型数据,可以自动进行类型转换

(6)如果函数返回的类型和return语句中表达式的值的数据类型不一致,则以函数返回类型为准,即 函数返回类型决定返回值的类型。对数值型数据,可以自动进行类型转换.

四、函数的调用

(1)函数在定义后,如果不被调用是不会被执行的

(2)main函数是C程序的主函数,是会被自动执行的且只有一个main函数

1、无参函数的调用

//无参数函数的调用方法
/*
    函数名(实参列表)
    或者
    变量 = 函数名(实参列表)
*/

#include <stdio.h>

int fun1()
{
    retur 10;
}

int main()
{
    fun1();    //调用fun1函数
    int x = fun1();
    return 0;
}

注意 :当函数有返回值时,我们可以定义一个变量来接收函数的返回值,但是定义变量的数据类型必须和函数的返回类型一致,当然我们也可以不接收函数的返回值。

2、有参函数的调用

//有参数函数的调用方法
/*
    函数名(实参列表)
    或者
    变量 = 函数名(实参列表)
*/

#include <stdio.h>

int fun1(int a,int b)
{
	printf("%d",a);
    return 0;
}

int main()
{
    int a = 10;
    int b = 11;

    fun1(a,b);
	
	return 0;	

}

注意:实参的个数和形参的个数必须一致

五、函数的嵌套调用

指某个函数的函数体中调用了另外一个函数

//执行逻辑

#include <stdio.h>

void b()  //定义函数b
{
    printf("b\n");
}

void a()  //定义函数a
{
    pirntf("a\n");
    b();  //函数a中调用函数b
}

int main()
{
    a();
    return 0;
}

执行顺序:

六、函数的声明

 1、在上一个例子中,如果我们将函数a和b的位置互换,我们编译程序看看会发生什么情况

#include <stdio.h>

void a()
{
    printf("a\n");
    b();
}

void b()
{
    printf("b\n");
}

int main()
{
    a();
    return 0;
}



当编译后,我们发现编译报warning了,意思时函数b被隐式的声明了

虽然编译后报了warning,但是代码还是能够重新编译的,并且能够正常的执行,如果是第版本的编译器,可能就会编译报错,并且显示函数b是未声明的。

注意:在编译程序时要将warning当error!

接下来我们思考一下,为什么程序编译会报warning甚至是error呢?

答:因为编译器在编译代码时,如果代码中有调用函数的语句,那么会在该语句之前检索函数是否有被声明或者定义,如果没有则编译报warning或者error!

解决的方法:

(1)将函数b的定义放在函数a之前

(2)在代码的前面部分对函数b进行声明

如:void b();

 2、函数声明语法

函数类型 函数名 (形参列表)
注意:
1、函数声明时,函数类型(返回值类型)必须与函数实现时一致,函数名必须和函数实现时一致
2、形参列表中,可以不填写形参变量的名字,只需要填写形参的类型即可,例如:
int fun(int, float);

七、局部变量和全局变量

1、定义在{}内的变量,称为局部变量

2、局部变量的作用域:所在的{}内

3、局部变量的生命周期随着{}的结束而结束

#include <stdio.h>

void func()
{
 int func_x = 100; //局部变量
}

int main()
{
     int i = 10;//局部变量
     {
         int i = 100; //局部变量
         printf("%d\n", i); // 100
         
         int j = 100; //局部变量
     }
    
     printf("%d\n", i); // 10
     printf("%d\n", j); //编译报错:error: 'j' undeclared
     printf("%d\n", func_x);//编译报错:error: 'func_x' undeclared
     
     return 0;
}

八、全局变量

1、定义在函数外部的变量称之为:全局变量

2、全局变量的初始化

3、全局变量的作用域是整个程序

4、全局变量的生命周期:随着程序的结束而结束

注意:全局变量在定义时如果不初始化,编译器会将值设置为默认值0

#include <stdio.h>

int cnt = 100; //全局变量

void func()
{
    int func_c = 100; //局部变量
    cnt++;
}

int main()
{
    func();
    printf("cnt:%d\n",cnt);
    return 0;
}

九、递归函数

1、递归函数的定义

一个函数在它的函数体内调用自身称为递归调用,这种函数称为递归函数

//例如
void func()
{
    func();   
}

2、递归函数的使用

(1)思考:什么时候需要使用递归函数

答:在实现某个函数的过程中,函数的某个功能的实现与本函数一样,则使用函数的递归

(2)思考:如果函数的递归调用是(看下图)的模式,会出现什么情况

void func()
{
    func();
}

//注意:函数递归调用一定要有退出条件!!!

答:结果是,会出现死循环的情况,所以强调函数的递归调用一定要有退出的条件

3、实例:求n的阶乘

#include <stdio.h>
#include <stdlib.h>

long long int factorial(int n)
{
    long int result;
    if(n >= 17){
        printf("越界\n");
        exit(-1);
    }
    if(n == 1){
        result = 1;
    }else{
        result = n*factorial(n-1);
    }
    return result;
}

int main()
{
    int n;
    long long int ret;
    printf("输入一个整数\n");
    scanf("%d",&n);
    ret = factorial(n);
    printf("结果:%ld",n,ret);
    printf("%d\n",sizeof(long int));
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值