自定义函数的使用

本文详细介绍了C语言中函数的概念,包括主函数的作用、自定义子函数的定义、声明和调用,以及值传递、地址传递和数组传参的区别。还讲解了静态局部变量和指针函数的相关知识。
摘要由CSDN通过智能技术生成

函数

主要是为了封装代码,减少重复

1.主函数:一个项目或者一个工程都是有且仅有1个主函数,程序的运行都是从main函数开始,终止于 main 函数;

2.自定义子函数:即自己写的函数用来实现某些特定功能;

一般,默认自定义子函数在主函数后面编写,此时使用子函数时,需要在main函数前声明,但如果子函数在main前,可不声明。

一.自定义子函数

      函数的定义 -- 函数实现功能的整个过程;

      函数的声明 -- 告诉编译器,该函数存在;

      函数的调用 -- 函数真正的运行;

#include <stdio.h>

int Fun(int a,int b);//函数的声明,告诉编译器,该函数存在

int main()
{
	int a = 12,b = 13,sum = 0;
	sum = Fun(a,b);//函数的调用,实现定义函数的真正运行
	printf("sum=%d\n",sum);
	return 0;
}

//函数的定义,定义函数实现功能的过程
int Fun(int a,int b)
{
	int sum=a+b;
	return sum;
}

   1.函数的定义:

格式:返回值类型 函数名(形参类型 形参名,形参类型 形参名……)//函数头

{

        函数体;

        return 返回值;

}

//函数的定义,定义函数实现功能的过程
int Fun(int a,int b)//返回值类型:int,函数名:Fun, 形参列表:(int a,int b),
{
	int sum=a+b;//函数体,实现需要的功能:求和
	return sum;//返回sum,sum的数据类型为int,所以定义的函数的返回值类型也为int
}//若无返回值,可以用void,即void 函数名 (形参列表)

函数名:遵循标识符命名规则;驼峰式:Dht11_Init

返回值类型:和return后面的具体的返回值保持一致即可;无返回值:返回值类型写void;(:返回值只能返回一个数!)

形参:函数在定义的时候写在函数名后面的小括号种的参数。:如果没有形参,用void或者不写;形参类型和形参名必须一一对应;形参列表也叫做定义变量,在形参列表定义过的变量,直接在函数体使用即可,不能再重复定义)

   2.函数的声明

格式:函数头;//告诉编译器,该函数存在,注意分号

位置:放在调用它的函数的上面,一般统统放在main函数的上面;


int Fun(int a,int b);//函数的声明,告诉编译器,该函数存在

int main()
{
	……

	return 0;
}

   3.函数的调用

格式:返回值类型 变量名=函数名(实参);

int main()
{
	int a = 12,b = 13,sum = 0;
	sum = Fun(a,b);//函数的调用,实现定义函数的真正运行
	printf("sum=%d\n",sum);
	return 0;
}

返回值类型和等号后面函数的返回值类型保持一致;

变量名,符合标识符命名规则;

函数名,调用的函数的函数名;

实参,函数被调用的时候,括号里面的提供的叫实参。:如果没有形参,实参就不用提供,什么都不写;实参可以是变量,表达式,常量,地址,数组;实参不能写数据类型)

二.形参和实参

  • 形参的起始值来自于实参
  • 实参的个数和位置必须和形参一一对应,传参也按照对应位置传递
  • 形参和实参各自占用不同的内存空间
  • 形参名和实参名可以一样,也可以不一样,各自是各自的局部变量

函数调用的其他格式:

有参有返: 返回值类型 变量 = 函数名(实参);

有参无返: 函数名(实参);

无参有返: 返回值类型 变量 = 函数名();

无参无返: 函数名();

注意:子函数执行:只有被调用,才能执行,并且只有被调用计算机才分配空间:子函数执行完,空间会被释放!)

三.函数传参:

   1.值传递:

形参的起始值来自于实参,形参的变化不会引起实参的改变

形参和实参各自占用不同的内存空间

#include <stdio.h>
void Swap(int a,int b);//声明
int main()
{
	int a=10,b=99;
	printf("main:a = %d,b = %d\n",a,b);
	//a = 10,b = 99
	Swap(a,b);//调用
	printf("调用后main:a = %d,b = %d\n",a,b);
	//a = 10,b = 99;
	return 0;
}

void Swap(int num1,int num2)//定义
/* num1和num2仅仅起始值来自于主函数的a和b,和主函数的a和b占据不同的存储空间,改变子函数的num1和num2的值,主函数的a和b不会随着改变*/
{
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
	printf("Swap:num1 = %d,num2 = %d\n",num1,num2);
	return;
}

运行结果:

main:a = 10,b = 99
Swap:num1 = 99,num2 = 10
调用后main:a = 10,b = 99

   2.地址传递:

传递变量的地址,通过指针,改变指针指向的空间内容!

#include <stdio.h>

void Swap(int *p,int *q);

int main()
{
	int a=10,b=99;
	printf("main:a = %d,b = %d\n",a,b);
	Swap(&a,&b);
	printf("调用后main:a = %d,b = %d\n",a,b);
	return 0;
}
void Swap(int *p,int *q)
{
	//p里面存的是a的地址,*p直接找到a,改变*p空间的内容就可以改变a
	//q里面存的是b的地址,*q直接找到b,改变*q空间的内容就可以改变b
	int tmp = *p;   
	*p = *q; //改变*p空间的内容就可以改变a
	*q = tmp;//改变*q空间的内容就可以改变b
	
	return;
}

运行结果:

main:a = 10,b = 99
调用后main:a = 99,b = 10

数组传参:属于地址传递,写数组名->数组名表示数组的首元素地址

#include <stdio.h>
int Sum(int *p);
int main()
{
	int num[6] = {1,2,3,4,5,6};

	int a = Sum(num);//实参不写数据类型,数组名=首元素地址
	printf("数组的和:%d\n",a);
	return 0;
}
int Sum(int *p)//int *p=num;传递num的首地址
{
	int sum = 0;
	for(int i=0;i<6;i++)
	{
		sum += *(p+i);
	}
	return sum;
}

(子函数的数组相当于局部变量,当调用完后,子函数的空间被释放,引入static)

static修饰的局部变量:和全局变量一样,从定义处开始,到当前函数结束;

#include <stdio.h>
int *Fun(void);
int main()
{
	int *p = Fun();
	for(int i=0;i<6;i++)
	{
		printf("%d\n",*(p+i));
	}
	return 0;
}
//子函数只有被调用,才分配空间,使用完,空间会被释放!
int *Fun(void)
{
	static int num[6] = {1,2,3,4,5,6};//static 修饰,延长生命周期,类似全局变量
	return num;//数组名是首元素地址 &num[0],而num[0]的数据类型为:int *,所以Fun前的数据类型为int *
}

(全局变量,定义在函数体外部的变量,从定义处开始,到当前文件.c结束;局部变量,定义在函数体内部的变量,从定义处开始,到当前函数结束)

指针函数:返回值为指针的函数

函数指针:指向函数的指针

  • 50
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值