C语言中函数的使用(C#)

1. 函数的概念

在C语言中,函数是一段可以重复使用的代码块。它有一个名字,用于完成特定的任务,比如计算一个数学表达式的值或者实现某种数据处理。
 
函数可以接收数据(通过参数传递),也可以返回一个值。例如, int add(int a, int b) 是一个函数声明,它的名字是 add ,接收两个 int 类型的参数 a 和 b ,并且返回一个 int 类型的值。当你在程序中需要计算两个整数相加的结果时,就可以调用这个函数,而不用每次都写一遍相加的代码。

2. 库函数

在C语言中,函数是由C语言标准库提供的函数
 
这些函数预先编写好并经过测试,涵盖多种功能。比如 stdio.h 头文件里的 printf 函数,它用于格式化输出数据到控制台, scanf 函数用于从标准输入设备读取数据; math.h 头文件中有 sqrt 函数,能计算一个数的平方根。
 
库函数可以极大地提高编程效率,程序员不用自己编写代码去实现复杂的底层操作,只需要调用这些函数并按照要求传递参数就能实现对应的功能。

如何使用库函数?↓链接

https://cplusplus.com/

3. ⾃定义函数

在C语言中,自定义函数是由程序员自己编写的函数,用于完成特定的任务。
 
定义一个自定义函数的基本形式是:返回值类型 函数名(参数列表) {函数体}。例如,定义一个计算两个整数之和的函数:
 

int add(int a, int b) {
    return a + b;
}

在这个例子中, add 是函数名, int 是返回值类型,表示这个函数会返回一个整数。 (int a, int b) 是参数列表, a 和 b 是函数的参数,它们用于接收传入的数据。 {return a + b;} 是函数体,里面是实现函数功能的代码,这里是计算 a 和 b 的和并返回结果。
 
调用自定义函数和调用库函数类似,在需要的地方写函数名和传入相应的参数即可。例如

#include <stdio.h>
int main() {
    int num1 = 3, num2 = 5;
    int sum = add(num1, num2);
    printf("两数之和为 %d", sum);
    return 0;
}

在 main 函数中, add(num1, num2) 就是调用自定义的 add 函数,并把 num1 和 num2 的值传递进去,将函数返回的结果存储在 sum 变量中,再通过 printf 函数输出。

4. 形参和实参

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

实参 :真实传给函数的参数。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
参。
举栗子说明:
例如,定义一个函数来计算两个数的乘积
int multiply(int a, int b) {
    return a * b;
}
在这个函数定义中, a 和 b 就是形参。它们就像是函数内部定义的变量,用来接收外部传入的数据。
 
当调用这个函数时:
 
int main() {
    int x = 3;
    int y = 4;
    int result = multiply(x, y);
    // 这里x和y是实参
    return 0;
}
在 main 函数中调用 multiply 函数, x 和 y 就是实参。实参 x 的值 3 会被传递给形参 a ,实参 y 的值 4 会被传递给形参 b ,函数根据这些传入的值(也就是形参接收的值)进行计算,最后返回结果。

5. 函数的调用

1. 传值调用
 
定义:在传值调用中,函数被调用时,实参的值被复制一份传递给形参。在函数内部,形参是实参的一份临时拷贝,修改形参不会影响到实参。
例子:
 

#include <stdio.h>
void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    printf("在swap函数中,a = %d, b = %d\n", a, b);
}
int main() {
    int num1 = 3, num2 = 5;
    printf("在main函数中,交换前num1 = %d, num2 = %d\n", num1, num2);
    swap(num1, num2);
    printf("在main函数中,交换后num1 = %d, num2 = %d\n", num1, num2);
    return 0;
}


在这个例子中, swap 函数试图交换两个数的值。在 main 函数中调用 swap 函数时, num1 和 num2 的值被复制给 swap 函数中的 a 和 b 。在 swap 函数内部, a 和 b 的值被交换了,但是这种交换不会影响 main 函数中的 num1 和 num2 ,因为 a 和 b 是 num1 和 num2 的副本。


2. 传址调用
 
定义:在传址调用中,实参是一个地址(如变量的地址),函数被调用时,这个地址被传递给形参。这样形参和实参指向同一块内存空间,在函数内部对形参所指向的内存空间进行修改,就会影响到实参的值。
例子: 

#include <stdio.h>
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
    printf("在swap函数中,*a = %d, *b = %d\n", *a, *b);
}
int main() {
    int num1 = 3, num2 = 5;
    printf("在main函数中,交换前num1 = %d, num2 = %d\n", num1, num2);
    swap(&num1, &num2);
    printf("在main函数中,交换后num1 = %d, num2 = %d\n", num1, num2);
    return 0;
}


这里 swap 函数的参数是指针类型( int *a 和 int *b )。在 main 函数中调用 swap 函数时,传递的是 num1 和 num2 的地址( &num1 和 &num2 )。这样, swap 函数中的 *a 和 *b 就分别指向 main 函数中的 num1 和 num2 所占据的内存空间,对 *a 和 *b 的修改会直接影响 num1 和 num2 的值。

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

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

6.1嵌套调用

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。

函数嵌套调用的例子: 

#include <stdio.h>
// 函数add用于计算两个数的和
int add(int a, int b) {
    return a + b;
}
// 函数calculate用于先计算两个数的和,然后再加10
int calculate(int x, int y) {
    int sum = add(x, y);
    return sum + 10;
}
int main() {
    int num1 = 5;
    int num2 = 3;
    int result = calculate(num1, num2);
    printf("结果是: %d\n", result);
    return 0;
}

 
↑代码 解释:

  • 首先定义了一个函数 add ,它接受两个整数参数 a 和 b ,并返回它们的和。
  • 然后定义了函数 calculate ,这个函数接受两个整数参数 x 和 y 。在 calculate 函数内部,它调用了 add 函数来计算 x 和 y 的和,并将结果存储在 sum 变量中。接着, calculate 函数将 sum 的值再加10,并返回这个结果。
  • 在 main 函数中,定义了 num1 和 num2 两个变量,然后调用 calculate 函数,将 num1 和 num2 作为参数传递进去。最后,将 calculate 函数返回的结果存储在 result 变量中,并通过 printf 函数输出结果。

6.2链式访问

把一个函数的返回值作为另外一个函数的参数。
#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    //结果是啥?
    //printf函数的返回值是打印在屏幕上字符的个数
    return 0;
}
//结果是4321

7.函数的声明和定义

7.1.1函数声明

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


函数声明是一种告诉编译器函数的基本信息(返回值类型、函数名和参数类型)的语句。它的形式一般为“返回值类型 函数名(参数类型列表);”。例如,有一个函数用于计算两个整数相加,函数声明可以写成 int add(int a, int b); 。


7.1.2 为什么要声明函数?


 假设没有函数声明,看下面的代码:

#include <stdio.h>
int main() {
    int result = add(3, 5);
    printf("结果是 %d", result);
    return 0;
}
int add(int a, int b) {
    return a + b;
}

当编译器编译 main 函数中的 add(3, 5) 时,它还没看到 add 函数的定义,不知道 add 函数需要什么样的参数和返回什么类型的值。这可能会导致编译器产生警告或者错误。
加上函数声明后:
 

#include <stdio.h>
int add(int a, int b);  //函数声明
int main() {
    int result = add(3, 5);
    printf("结果是 %d", result);
    return 0;
}
int add(int a, int b) {
    return a + b;
}


有了函数声明,编译器就能找得到add函数,这样在编译 main 函数中的 add 函数调用部分时,就可以检查参数类型和数量是否正确,避免一些潜在的错误,并且也让代码结构更加清晰,方便阅读者理解函数的输入和输出情况。

7.2.1 函数的定义

函数定义是对函数功能的具体实现,包括函数头和函数体。函数头说明了函数的返回值类型、函数名和参数列表;函数体则是用花括号括起来的一组语句,用于完成特定的操作。


7.2.2 举例
 以下是一个简单的函数定义,用于计算两个整数的和:

int add(int a, int b) {
    return a + b;
}

在这个例子中:
 int 是返回值类型,表示这个函数执行完后会返回一个整数。
{return a + b;} 是函数体,这里只有一条语句,它计算 a 和 b 的和并返回结果。当在程序的其他地方调用 add 函数时,就会执行这个函数体中的语句来得到两个数的和。

8. 数组做函数参数

1. 值传递(传递数组名)
当把数组名作为参数传递给函数时,实际上传递的是数组的首地址,这属于传址调用。例如:
 

#include <stdio.h>
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
int main() {
    int myArray[] = {1, 2, 3, 4, 5};
    int size = sizeof(myArray)/sizeof(myArray[0]);
    printArray(myArray, size);
    return 0;
}


  这里 printArray 函数的参数 arr 接收了 myArray 的首地址,函数通过这个地址访问数组元素,所以在函数内部可以操作并输出数组的内容。这种方式使得函数能够对原始数组进行操作,而不是副本。
2. 数组大小的不确定性
在函数参数中, int arr[] 这样的声明方式,编译器不会检查数组的实际大小。例如:
 

void wrongFunction(int arr[]) {
    // 编译器不会检查数组大小,可能导致越界访问
    printf("%d", arr[10]);
}

所以在写函数时,通常需要另外传递一个表示数组大小的参数,像前面 printArray 函数中的 size 参数,以避免数组越界访问等错误。

9.函数递归——>https://blog.youkuaiyun.com/qq_64176311/article/details/144446935?spm=1001.2014.3001.5501

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

今天学习了么!?

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

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

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

打赏作者

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

抵扣说明:

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

余额充值