天天看点

C语言函数(函数的分类,参数,调用,声名及定义)

(文章目录)

一、C语言中函数的分类

  1. 库函数
  2. 自定义函数

库函数:在开发的过程中,每个程序员都可能用得到,为了支持可移植性和提高程序的效率,C语言基础库中提供了一系列类似(strcpy:字符串拷贝函数)库函数,方便程序员进行开发。

查找和学习库函数可以简单看看:cplusplus官网

库函数有:

  • IO函数:如:printf scanf getchar putchar 等
  • 字符串操作函数:如:strcmp strlen 等
  • 内存操作函数:如:memcpy memcmp memset 等
  • 时间/日期函数:如:time 等
  • 数学函数:如:sqrt pow 等
  • 其他函数

    这里就不多介绍了

函数中更加重要的是自定义函数:

自定义函数:和库函数一样有函数名,返回类型和函数参数,但是不一样的是这些都要我们自己设计。

函数组成如图:

C语言函数(函数的分类,参数,调用,声名及定义)

例如:函数求两个数的最大值:

int get_max(int x, int y)
{
	int z = 0;
	if (x > y)
		z = x;
	else
		z = y;
	return z;//返回函数多的最大值
}
int main()
{
	int a = 10;
	int b = 20;
	//函数的调用
	int max = get_max(a, b);
	printf("%d\n", max);//打印20
	return 0;
}
           

二、函数的参数及调用

写一个函数交换两个数的值:

  • 第一种方式实现:
//函数返回类型void,表示函数不返回任何值。
void Swap1(int x, int y)
{
	int z = 0;
	z = x;
	x = y;
	y = z;
}
int main()
{
	int a = 10;
	int b = 20;
	//写一个函数交换两个整型变量的值
	printf("交换前:a=%d b=%d\n",a, b);
	Swap1(a, b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}
           

打印出来如图并没有交换两个数的值:

C语言函数(函数的分类,参数,调用,声名及定义)

通过调试我们看到:a, b和x,y 所占用的内存地址不一样。交换x,y的值不影响 a,b的值。

所以这个代码并不能实现我们想要的效果。

C语言函数(函数的分类,参数,调用,声名及定义)
  • 第二种使用指针实现
void Swap2(int* pa, int* pb)
{
	int z = 0;
	z = *pa;
	*pa = *pb;
	*pb = z;
}
int main()
{
	int a = 10;
	int b = 20;
	//写一个函数交换两个整型变量的值
	printf("交换前:a=%d b=%d\n", a, b);
	Swap2(&a, &b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}
           

打印成功交换两个数的值

C语言函数(函数的分类,参数,调用,声名及定义)
C语言函数(函数的分类,参数,调用,声名及定义)
  • 实际参数(实参):真实传给函数的参数,叫实参。真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
  • 形式参数(形参):形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元) ,所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

上面Swap1和Swap2函数中的参数x,y, px, py都是形式参数。在main函数中传给Swap1的a ,b和传给Swap2函数的&a , &b是实际参数。

Swap1函数属于传值调用 在被调用的时候,实参传给形参,其实形参是实参的一份临时拷贝。改变形参不改变实参。

Swap2函数属于传调用址 在被调用的时候由于传的是地址,形式参数的指针指向a,b的地址,通过指针变量就可以直接改变a,b的值。

  • 传值调用:

    函数的形参和实参分别占用不同的内存块,对形参的修改不会影响实参,形参是实参的一份临时拷贝。改变形参不改变实参。

  • 传址调用:

    传址调用是把函数外部创建的内存地址传递给函数参数的一种调用方式。

    这种传参方式可以让函数和函数外边的变量建立其起真正的联系,也就是函数内部可以直接操作函数外部的变量

三、函数的嵌套调用和链式访问

函数的嵌套调用:

void test2()
{
	printf("hehe\n");
}

int test1()
{
	test2();
	return 0;
}

int main()
{
	test1();
	return 0;
}
//运行函数打印“hehe”
           

函数的链式访问:

把一个函数的返回值作为另一个函数的参数

int main()
{
	int len = strlen("abc");
	printf("%d\n", len);
	//链式访问
	printf("%d\n",strlen("abc"));
	return 0;
}
           

下面看一个代码这是一个典型的链式访问:

printf("%d",printf("%d",printf("%d", 43)));
           
C语言函数(函数的分类,参数,调用,声名及定义)

为什么会打印 4321 呢?

我们看一下函数 printf

int printf( const char *format [, argument]... );

返回值:Each of these functions returns the number of characters printed, or a negative value if an error occurs.(每个函数都返回打印的字符数,如果出现错误,则返回负值。)

C语言函数(函数的分类,参数,调用,声名及定义)

四、函数的声名和定义

  • 告诉编译器有一个函数叫什么,参数是什么,返回类型是什,但是具体是不是存在,无关紧要。
  • 函数声名一般出现在函数的使用之前,要满足先声名后使用。
  • 函数的声名一般要放在头文件中。
int main()
{
	int a = 10;
	int b = 20;
	//函数先声名一下 --> 告知
	int get_max(int, int); // int get_max(int x, int y);都可以
	//函数的调用
	int max = get_max(a, b);
	printf("%d\n", max);//打印20
	return 0;
}
int get_max(int x, int y)
{
	int z = 0;
	if (x > y)
		z = x;
	else
		z = y;
	return z;//返回函数多的最大值