函数相关内容

目录

1.概念

2.库函数

2.1标准库和头文件

2.2使用 

2.3格式 

3.自定义函数 

3.1语法格式

3.2例子 

3.3形参和实参

3.3.1实参

3.3.2形参

3.3.3形参实参

3.4.return

3.5.数组做函数参数 

3.6.嵌套调用和链式访问

3.6.1嵌套调用

3.6.2链式访问

3.7函数声明和定义

3.7.1单个文件

 3.7.2多个文件

3.7.3static和extern

3.7.3.1作用域

3.7.3.2生命周期

3.7.3.3static

3.7.3.4extern


1.概念

函数在c语言中是一个完成某项特定任务的一小段代码,也叫子程序。函数需要特定写法和调用方法。

c语言程序由无数个小的函数组成。一个任务包含了若干个函数。

函数一般有2类:库函数、自定义函数。

2.库函数

2.1标准库和头文件

c语言不提供函数,只是规定了语法规则。c语言的国际标准ANSI C有一些常用函数的标准,叫标准库。不同编译器厂商根据ANSI提供的标准给出了一系列的新函数,称为库函数。

库函数相关头文件:C 标准库头文件 - cppreference.com

2.2使用 

库函数需要提前在标准库中的头文件中声明,才能使用。

学习查看工具:

c/c++官方链接:C 标准库头文件 - cppreference.com

cplusplus.com:C library - C++ Reference (cplusplus.com)

#include <stdio.h>
#include <stdlib.h>
int main()
{
    srand((unsigned int)time(NULL));
    int r=rand()%100-1;
    printf("随机数:%d",r);
    return 0;
}

2.3格式 

 库函数文档格式:

函数原型;函数功能介绍;参数和返回类型说明;代码举例;代码输出;相关知识链接

3.自定义函数 

3.1语法格式

ret_type fun_name(形式参数)
{

}
//ret_type是函数返回类型
//fun_name 是函数名
//括号中放的是形式参数
//{}这里是函数体

 ret_type是用来表示函数计算结果类型,void表示什么都不返回。

fun_name是为了方便使用函数,方便调用。名字也要有意义

参数也可以是void,表示没有参数。有参数,要交代函数类型和名字、个数

函数体是完成计算的过程

3.2例子 

#include <stdio.h>
int ADD(int x, int y)//参数,具体值由主函数给出
{
	int z = 0;
	z = x + y;
	return z;//返回值是一个z的变量存储的值
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int r = ADD(a, b);//a,b对应x,y.整个add(a,b)对应的就是add函数中的返回值即z变量存储的值
	printf("%d\n", r);
	return 0;
}

函数部分要交代清楚:参数个数,参数类型,参数名字。

3.3形参和实参

函数的参数分为形参和实参

3.3.1实参

根据上面的代码,在主函数中括号内的a,b就是传递给函数的参数,称为实际参数,实参。实参就是实际给函数的参数

3.3.2形参

在add函数定义中,x,y就是形式参数,形参

不调用add函数的话,x,y只是形式上存在,不占内存空间,不真实存在。当函数被调用,有实参传递过来后,才会占用内存空间,这个过程称为形参的实例化。

3.3.3形参实参

形参和实参存储的地址是不同的,实参的传递类似于将实参的值拷贝给形参。

3.4.return

return 后面可以什么都没有,适用于函数返回类型void

return返回的值和函数返回类型不一样,系统会自动将返回值隐式转换为函数的返回类型。

当return执行后,函数就已经返回了值,在这个函数内return后面的语句不会被执行,因此通常放最后。

若函数中有if等分支语句,每种情况下的参数应该都有return返回,否则会错误。

3.5.数组做函数参数 

数组传参:

1.形参和实参个数匹配

2.实参是数组,形参也能写成数组

3.形参是一维数组,数组大小可省略

4.形参是二维,行可省,列不可省

5.数组传参,形参不会创建新数组

6.形参操作的数组和实参操作的数组实际是同一个

举例:将一个整型数组的内全部写为-1,并且打印。

#include<stdio.h>
void set_arr(int arr[], int sz)//此处的arr[]和sz是形参,具体的值在主函数中给入
{
	int i = 0;
	for (i = 0; i < sz; i++)//赋值-1
	{
		arr[i] = -1;
	}

}
void print_arr(int arr[], int sz)//此处的arr[]和sz是形参,具体的值在主函数中给入
{
	int i = 0;
	for (i = 0; i < sz; i++)//打印数组
	{
		printf("%d", arr[i]);
	}

}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };//初始化数组
	int sz = sizeof(arr) / sizeof(arr[0]) ;//计算数组大小
	set_arr(arr, sz);//调用函数
	print_arr(arr, sz);
	return 0;
}

3.6.嵌套调用和链式访问

3.6.1嵌套调用

嵌套调用是函数之间的互相调用。

例子:计算某年某月有多少天。

实现函数:rn()       shu()

#include <stdio.h>
int rn(int nian)//判断闰年的函数
{
	int z = 0;
	if (nian % 4 == 0 && nian % 100 != 0 || nian % 400 == 0)
	{
		z = 1;
	}
	else
	{
		z = 0;
	}
	return z;//返回值
}

int shu(int nian,int y)//判断月份天数
{
	int days[] = { 0,31,28,31,30,31,30,31,30,31,30,31 };
	int day = days[y];
	if (rn(nian) == 1 && y == 2)
	{
		day++;
	}
	return day;
}

int main()
{
	int nian = 0;
	int y = 0;
	scanf("%d %d", &nian, &y);
	int da = shu(nian, y);
	printf("%d", da);
	return 0;
}

注意,函数不能嵌套定义

3.6.2链式访问

链式访问指的是将一个函数的返回值作为另外一个函数的参数。包括库函数和自定义函数

举例1:

#include <stdio.h>
int main()
{
	printf("%d", strlen("www"));//链式访问,将strlen函数作为一个参数放入printf函数

	return 0 ;
}

注意,在链式访问时要注意函数的返回值究竟是什么,比如strlen返回值是字符串长度

printf函数的返回值是打印的字符个数

 第一个printf打印了100,返回值是3

第二个pirntf打印了3,返回值是1

第三个printf打印了1,返回值1

所以最终是(第一个)100(第二个)3(第三个)1

3.7函数声明和定义

3.7.1单个文件

一般使用函数时,直接写出来

比如上面月份天数的代码

#include <stdio.h>
int rn(int nian)//判断闰年的函数
{
	int z = 0;
	if (nian % 4 == 0 && nian % 100 != 0 || nian % 400 == 0)
	{
		z = 1;
	}
	else
	{
		z = 0;
	}
	return z;//返回值
}

int shu(int nian,int y)//判断月份天数
{
	int days[] = { 0,31,28,31,30,31,30,31,30,31,30,31 };
	int day = days[y];
	if (rn(nian) == 1 && y == 2)
	{
		day++;
	}
	return day;
}

int main()
{
	int nian = 0;
	int y = 0;
	scanf("%d %d", &nian, &y);
	int da = shu(nian, y);
	printf("%d", da);
	return 0;
}

int rn和int shu的部分都是函数的定义,而直接将函数写入函数体的部分则为函数的调用。

但要注意:因为c语言程序是逐行执行的,如果先调用再定义,编译器就会报错。

为了避免这种报错,可以选择声明函数

声明函数需要交代:函数名、函数返回类型、函数参数

比如int rn(int nian);       参数可以只给类型,省略名字

下面的代码提前声明了rn函数,尽管函数的调用在定义前,但还是能识别,函数的定义也是一种特殊的声明。

#include <stdio.h>
int rn(int nian);

int shu(int nian,int y)//判断月份天数
{
	int days[] = { 0,31,28,31,30,31,30,31,30,31,30,31 };
	int day = days[y];
	if (rn(nian) == 1 && y == 2)
	{
		day++;
	}
	return day;
}

int main()
{
	int nian = 0;
	int y = 0;
	scanf("%d %d", &nian, &y);
	int da = shu(nian, y);
	printf("%d", da);
	return 0;
}

int rn(int nian)//判断闰年的函数
{
	int z = 0;
	if (nian % 4 == 0 && nian % 100 != 0 || nian % 400 == 0)
	{
		z = 1;
	}
	else
	{
		z = 0;
	}
	return z;//返回值
}

 3.7.2多个文件

实际写程序时,代码量可能比较多,因此不会将所有代码都放在一个文件中。

一般情况,函数声明、类型的声明都放在头文件(.h)中,函数的定义放在一个源文件(.c/.cpp)中,函数的调用在主函数源文件(.c/.cpp)中,从而方便书写。

3.7.3static和extern

static和extern都是c语言的关键字

static是静态,用来:修饰局部变量、修饰全局变量、修饰函数

extern是用来声明外部符号

3.7.3.1作用域

程序中用到的名字不一定都是有效的,限定名字的可用范围就是名字的作用域

1.局部变量的作用域是变量所在的局部范围,比如一个for循环里定义的变量只能在这个for循坏里使用,不能在这个for循坏外面使用

2.全局变量的作用域是整个工程

3.7.3.2生命周期

指变量的创建(申请内存)到变成的销毁(收回内存)之间的一个时间段

1.局部变量:进入作用域生命周期开始,到出作用域生命周期结束

2.全局变量的生命周期是:整个程序的开始到结束

3.7.3.3static

修饰局部变量时,可以让变量的生命周期延长,达到全局变量的生命周期,也就是说变量存储的值在出了作用域也会一直存储,而不是释放内存。但作用域没有变化。

本来局部变量是存储在内存的栈区,但static修饰局部变量后会改为存储在静态区。

3.7.3.4extern

当想将一个a文件定义的符号在b文件里调用,就需要用extern来声明

例如extern int a;

当在一个源文件定义一个全局变量后,其他源文件通过extern就能调用这个变量,但是如果用static来修饰全局变量后,就不能在被其他源文件调用。

全局变量默认是带有外部链接属性的,而static修饰全局变量后,就变成内部链接属性了,无法被外部文件调用。

函数也是如此,当被static修饰后,就无法被其他文件调用,作用域被限定在本源文件,生命周期没有变。函数默认也是外部链接属性

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值