C语言之函数(中)

1. 函数的参数

实际参数(实参)

在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”(简称“实参”)。
实参可以是常量、变量或表达式, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。
当实参不止一个时,用逗号将其分割开。

形式参数(形参)

形式参数是指函数名后括号中的变量,目的是用来接收调用该函数时传入的参数,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效

对于下面的代码,Swap1和Swap2函数中的数 x,y,px,py 都是形式参数。在main函数中传给Swap1的num1,num2和传给Swap2函数的&num1,&num2是实际参数

#include <stdio.h>
void Swap1(int x, int y)
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
void Swap2(int* px, int* py)
{
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	Swap1(num1, num2);
	printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
	Swap2(&num1, &num2);
	printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
	return 0;
}

我们可以通过调试中的监视窗口看出实参和形参的内存关系。
示例
形参实例化以后相当于实参的一份临时拷贝。

数组的传参

接收多维数组的函数,可以省略掉相当于开头下标的 N 维的元素个数,但是(N - 1)维之下的元素个数必须是常量。
一维数组至三维数组的参数声明示例如下;
void func(int arr[], int n);
void func(int arr[5],int n);

void func(int arr[][3], int n);
void func(int arr[5][3],int n);

void func(int arr[][2][3], int n);
void func(int arr[5][2][3],int n);
所接收的元素类型必须固定,但是元素个数是自由的。

2. 函数的调用

传值调用

传值调用是指函数在调用参数时,不是对原参数进行操作,而是创建参数的拷贝并对其进行操作,这种调用有利于保护数据。

Swap1的调用就属于传值调用

传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起正真的联系,也就是函数内部可以直接操作函数外部的变量
传址调用涉及到指针的内容,关于C语言指针的知识将会在我接下来的文章中有具体的讲解。

Swap2的调用就属于传址调用

使用区别

  1. 当函数需要对外部变量进行修改时,就需要使用传址调用。
  2. 当函数不需要对外部变量进行修改时,只需要外部变量的数值大小时,可以使用传值调用,也可以使用传址调用,但是在使用传址调用是,最好对形参进行 const 修饰,避免外部变量被修改。

函数调用的方式

C语言中,所有的执行语句都只能出现在函数之中。同样,函数的调用也只能出现在某函数的函数体内。函数的调用以两种方式出现:函数的嵌套函数的递归

3. 函数的嵌套调用和链式访问

函数的嵌套

C语言中,所有函数的定义都是互相平行和独立的,一个函数的定义不能包含另一个函数的定义,即不允许函数的嵌套定义。但函数的调用可以通过用一个函数调用另一个函数来实现,这就形成了函数的嵌套调用。C语言不限制嵌套的个数和层数,这样就可以自由,合理的组织程序的模块结构。

例如:

void print_line(int line)
{
	int i = 0;
	for(i = 0; i < line; i++)
	{
		printf("* ");
	}
	printf("\n");
}

void print_triangle(int length)
{
	int i = 0;
	for(i = 0; i < length; i++)
	{
		print_line(i + 1);//调用 print 打印三角形的每一行
	}
}

int main()
{
	printf("请输入等腰直角三角形的直角边长度");
	int length = 0;
	scanf("%d" ,&length);
	print_triangle(length);//调用函数打印三角形
	return 0;
}

链式访问

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

#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    return 0;
}

这段代码执行之后的结果是什么?
想要知道这段代码的执行结果,我们就要深刻了解一下printf函数的返回值
printf函数的返回值
查询cplusplus中对 printf 返回值的解释,我们可以知道,printf 函数的返回值为写入的字符总数,当写入字符错误的时候,printf 函数的返回值为一个负数,以此作为写入错误的提醒。
所以代码执行的结果为:
代码执行结果

4. 函数的声明和定义

声明

  1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,无关
    紧要。
  2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用
  3. 函数的声明一般要放在头文件中的。

定义

函数的定义是指函数的具体实现,交待函数的功能实现。

使用方式

当程序内容比较少的时候,函数声明可以和定义放在一起,函数在定义时就已经包含声明了。为了保证先声明后使用。一般函数的声明和使用都会放在主函数的前面,且被调用的函数放在调用函数之前。
当以后进入公司,程序都是多文件操作。这时函数的声明和定义就要分离。声明一般放在 .h 文件中,定义一般放在 .c 文件中。

例如:
在 Add.h 文件中

int ADD(int x, int y);//声明以分号结尾

在 Add.c 文件中

#include “Add.h”//在定义时需要包含声明所在的 .h 文件

int ADD(int x, int y)
{
	return (x > y) ? x : y;//函数的具体实现过程
}
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雾里看山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值