C语言函数超详细讲解

函数的概念

我们用百度百科搜出来数学中的函数概念

 其实在C语言中我们也要引入函数的概念

 C语言中函数可以翻译为子程序,C语言中的函数就是一个为了完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。

C语言的程序其实是由无数个小的函数组合而成的,也可以将一个大的计算任务可以分解成若干个较小的函数(对应较小的任务)完成。同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,也叫复用函数,提升了开发软件的效率。

 C语言中我们可以把函数分为:

库函数

自定义函数

我们先来讨论库函数

库函数

标准库和头文件

头文件中有函数的申明,库文件实现函数的定义。对于头文件和库的区别我们可以这样理解:就是头文件提供的是一个函数的声明,并没有这个函数具体代码,而库就是存放这个函数的具体实现代码。

 C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀ 些常⽤的函数的标准,被称为标准库,那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列 函数的实现。这些函数就被称为库函数。

 我们前⾯内容中学到的 printf 、 scanf 都是库函数,库函数的也是函数,不过这些函数已经是现 成的,我们只要学会就能直接使⽤了。有了库函数,⼀些常⻅的功能就不需要程序员⾃⼰实现了,⼀ 定程度提升了效率;同时库函数的质量和执⾏效率上都更有保证。各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头⽂件中进 ⾏了声明。

总结:

 // 1 c语言规定了语法规则
// 2 c语言本身不提供库函数
// 3 但是c语言规定了,一些库函数的各种信息
//   scanf-名字,参数,返回类型,函数的功能
//   priintf-
//   strlen- 
//让    C语言编译器的厂商根据规定实现这些函数
// 函数的实现细节可能有差异
// 但是程序员使用的时候,基本无感    

 库函数的使用方法

 我们用一个简单的sqrt来举例

 我们可以在写代码之前看这个文档中包含:

//库函数文档的一般格式
//1.函数原型
//2.函数功能介绍
//3.参数和返回类型说明
//4.代码举例
//5.代码输出
//6.相关知识链接

 

#include <stdio.h>
#include <math.h>
int main()
{
	double a = 16.0;
	double r = sqrt(16.0);
	printf("%lf", r);
	return 0;
}

结果为:

 自定义函数

ret_type fun_name(形式参数)

{

 ret_type 是函数返回类型 

fun_name 是函数名 

括号中放的是形式参数 

{}括起来的是函数体

 //自定义函数名是自定义的,根据实际情况起名字
//参数的个数也是根据实际情况而定,可以有0个参数,也可以有多个参数
//函数的返回值 函数可以返回值,也可以不返回值,要根据实际情况而定,函数不返回值时,返回类型写成void

 现学现用:我们用自定义来写一个两个数的加法

 

 

#include <stdio.h>
//int Add(int x, int y)
//{
//	int z;
//	z = x + y;
//	return z;
//}
//上述的代码可以简写为
int Add(int x, int y)//
{					 //函数的定义
	return x + y;	 //
}					 //

int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	int c=Add(a, b);//函数调用
	printf("%d", c);
	return 0;
}

 

形参和实参

 此时我们还用这个代码来研究:

int Add(int x, int y)//
{                     //函数的定义
    return x + y;     //
}                     //

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    int c=Add(a, b);//函数调用
    printf("%d", c);
    return 0;
}

 将代码调试起来,走你。

 我们在调试的可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不⼀样的,所 以我们可以理解为形参是实参的⼀份临时拷⻉。

 同理,我们还可以定义一个打印1~n的函数来继续研究实参和形参以及他们的关系,这个交给各位来研究。

void Print(int n)
{
	if (n < 1)
		return;
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		printf("%d ", i);
	}
}
int main()
{
	int m = 0;
	scanf("%d", &m);
	Print(m);

	return 0;
}

 小细节

//int test()
//{
//    return 3.5;
//}
//
//int main()
//{
//    int ret = test();
//    printf("%d\n", ret);
//    return 0;
//}

 如果上述代码int test()不加int,那么他结果还是3,因为默认是函数返回类型int类型

 return 语句

 

 函数的返回类型和返回参数

 加入有小伙伴想打印一个菜单,我们可以这样搞

void menu(void)
{
	printf("**************\n");
	printf("*****1.play***\n");
	printf("*****0.exit***\n");
}
int main()
{
	menu();
	return 0;
}

 

 接下来我们看一个问题代码:

void test()
{
    printf("hehe\n");
}
int main()
{
    test();
    test(1);
    test(100);
    test(100, 200);
    return 0;
}

 

 
//上述方式有些不合理,函数不需要传参,但传参数了,因此需要改为test(void)

 这个上述是不是我们提到过啊,要记住ok吗?

数组做函数参数

 

 

#include <stdio.h>
void set_arr(int arr2[],int sz2)
{
	int i = 0;
	for (i = 0; i < sz2; i++)
	{
		arr2[i] = -1;
	}
}

void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr1[] = {1,2,3,4,5,6,7,8,9,10};
	int sz1 = sizeof(arr1) / sizeof(arr1[0]);
	print_arr(arr1, sz1);//打印数组的所有内容
	set_arr(arr1,sz1);//将数组的元素全部设置为-1
	print_arr(arr1,sz1);//打印数组的所有内容
	return 0;
}

 

 

//此时数组名字叫arr,上次博客我们学到了,此时int []就是数组的类型
//要设置数组的所有内容,要遍历数组
//此时开启调试,监视arr1 arr2
//观察到arr1和2的地址一样
 

 

 小拓展:

//为什么说:C语言中scanf和printf函数的参数个数是不固定的
//知识点:可变参数
//printf("hehe");
//printf("%d %f",100,3.5);
//printf("%s %d %f","abc",10,5.5);

//int n=0;
//int m=0;
//scanf("%d",&n);
//scanf("%d %d",&n,&m);

 嵌套调用和链式访问

 

 

#include <stdio.h>
int is_leap_year(int y)
{
	if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
		return 1;
	else
		return 0;
}
int get_days_of_month(int y, int m)
{
	//31 28 31 30 31 30 31 31 30 31 30 31
	//   29
	int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31 };
	              // 1  2  3                         12
	int day = days[m];
	//闰年的2月是需要特殊调整 -29天
	if (is_leap_year(y) && m == 2)
	{
		day++;
	}
	return day;
}
int main()
{
	int year = 0;
	int month = 0;
	scanf("%d %d", &year, &month);
	int day=get_days_of_month(year, month);
	printf("%d\n", day);
	return 0;
}

 

刚才博主那个函数忘了写return day;调试到最后才发现哈哈,各位以后一定要仔细啊 

 


int main()
{
    size_t len=strlen("abcdef");
    printf("%zd\n", len);
    //上述的两行可以合并
    printf("%zd\n", strlen("abcdef"));//此时就是链式访问
    return 0;
}

我们接下来看一个有意思的:

 
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    //43 2 1
    //printf("%d", printf("%d ", printf("%d ", 43)));
    43 3 2
    return  0;
}

从Cplusplus网站上可以看到printf的返回值 

 

 

 

 int main()
{
    /*printf("%d", printf("%d", printf("%d", 43)));*/
    //43 2 1
    printf("%d", printf("%d ", printf("%d ", 43)));
    43 3 2
    return  0;
}

此时结果为多少呢,为4332为什么呢,有空格哈

//函数的声明和定义
int is_leap_year(int y)
{
	if ((y & 4 == 0 && y % 100 != 0) || (y % 400 == 0))
	{
		return 1;
	}
	else
		return 0;
}
int main()
{
	int year = 0;
	scanf("%d", &year);
	int ret = is_leap_year(year);
	if (ret == 1)
		printf("闰年\n");
	else
		printf("不是闰年\n");
}

我们一般都把函数定义写到主函数上。

其他的一些知识:

数组就到这里,下次见,有建议发评论区。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值