C语言——函数

前言

函数(function)是完成特定任务的独立程序代码单元

一、函数

函数是完成特定任务的独立程序代码单元

分为自定义函数(自己写的函数)和库函数(C语言内部提供的函数)

1.函数的定义

由函数头和函数体组成,而函数体包括了函数的返回类型、函数名、函数参数

返回类型 函数名(函数的参数)    //函数头
{
    语句项;    //函数体
}

其中,函数定义中的参数是形参,即形式参数;在调用函数时要传给函数的值叫做实参,即实际参数

2.函数的声明

函数声明就是告诉编译器有一个函数,这个函数的函数名、返回类型、参数都是什么

返回类型 函数名(参数1,参数2,...);

分号表明这是在声明函数,不是定义函数

3.函数的调用

函数调用就是使用函数

函数名(参数1,参数2,...);

括号里的参数是形参,函数调用时的实参传给形参

4.传值调用和传址调用

传值调用:函数的形参和实参分别占有不同的内存块,改变形参,不能改变实参

传址调用:把函数外部创建变量的内存地址传递给函数参数

对于传值调用,实参传给形参,其实形参是实参的一份临时拷贝

对于传址调用,函数内部可以通过函数接收的实参的地址从而访问实参,进而修改实参

二、写一个函数,交换两个整型变量的值

错误的函数定义(传值调用)

//写一个函数,交换两个整型变量的值
/*
思路:将函数定义为,创建一新变量z,将其
中一个变量x的值赋给z,另一个变量y的值再赋
给x,再将z变化后的值赋给y完成交换
*/
#include<stdio.h>
void exchange(x, y);    //函数声明

int main()
{
	int a = 22;
	int b = 33;

	printf("交换前:a=%d b=%d\n", a, b);
	exchange(a, b);        //函数调用
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

void exchange(int x, int y)    //函数定义
//(传值调用)
//exchange函数在被调用的时候,实参传给形参,其实形参是实参的一份临时拷贝
{
	int z = 0;    //实现两个值的交换,思路正确,但函数写法有误!!
	z = x;
	x = y;
	y = z;
}

在这里插入图片描述

运行结果:变量 a 和 b 的结果没有互换,函数并没有实现预先的要求

分析:a 和 b 的值确实分别传给了形 x 和 y,但函数交换的是形参 x、y 的值,并没有影响实参 a 和 b 的值,实参传给形参,形参是实参的一份临时拷贝;正确写法应为,将函数的形参改为指针变量,分别指向主函数中两个变量的地址,即通过指针访问到两个实参

正确的函数定义(传址调用)

将函数的参数修改为指针变量,分别指向主函数中两个变量的地址 (传址调用)

#include<stdio.h>
void exchange(x, y);

int main()
{
    int a = 22;
    int b = 33;
    
    printf("交换前:a=%d b=%d\n", a, b);
    exchange(&a, &b);
    printf("交换后:a=%d b=%d\n", a, b);
    return 0;
}

void exchange(int* x, int* y)    //(传址调用)
{
    int z = 0;  //*x和*y访问的就是主函数中的变量a和b
    z = *x;
    *x = *y;
    *y = z;
}

在这里插入图片描述

运行结果:成功实现两个变量的值的交换

三、考虑函数定义的位置

定义函数和调用函数的顺序也是有讲究的

比如在 main 函数中调用了一个函数,并且这个函数的定义是在 main 函数之后的,而又没有提前声明这个函数,那么这种写法就是不合法的

默认情况下,调用一个函数时,在调用的地方之前必须定义过这个函数

具体原因是,程序在第一次使用函数之前必须知道函数的类型,有两种写法:

1.把完整的函数定义放在第一次调用函数的前面

如主函数中调用了一个函数,那么这个函数的定义就得放在主函数前面

在这里插入图片描述

2.提前声明函数,把函数信息告知编译器

即在一个程序的开头就声明函数,那么这个函数的定义就写在后面的任意位置就可以了
在这里插入图片描述

总结

通用的写法是,将函数声明写在程序的开头;这样,函数的定义写在调用函数的位置的前面还是后面都可以

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

1、函数的嵌套调用

函数不能嵌套定义,但可以嵌套调用

#include<stdio.h>
int test3()
{
        printf("Hello!\n");
}
int test2()
{
        test3();
        return 0;
}
int main()
{
        test2();
        return 0;
}

2、函数的链式访问

函数的链式访问:把一个函数的返回值作为另一个函数的参数

#include<stdio.h>
#include<string.h>
int main()
{
        char arr1[10] = { 0 };
        char arr2[] = "Hello";

        printf("%s\n", strcpy(arr1, arr2));//(strcpy 函数:把arr2复制给arr1)
        return 0;
}

注:**strcpy 函数:**把一个字符串复制给另一个字符串

又例如:

int main()
{
        printf("%d", printf("%d", printf("%d", 66)));
        return 0;
}

注:printf()函数返回的是打印在屏幕上的字符的个数

分析:先执行第三个printf,即打印66,返回值为2,故第二个printf()打印2,同理第一个printf()打印1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

青春无限坑

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

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

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

打赏作者

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

抵扣说明:

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

余额充值