C语言函数的精解

1. 函数的概念

我们平时学的数学中就懂了函数是什么,如, y = kx + b,k和b都是常数,给定任意 x 就能求得 y

在C语言中,函数可以将一个大的任务给予一个函数,通过使用函数可以简化我们的代码,提升我们写代码的效率

C语言中函数我们已经学了很多了,如 printf 函数、scanf 函数等等,其实它们的底层逻辑都是很复杂的,但是标准库将底层逻辑封装成了简单的 printf 函数后,我们便可以很简单的将想要打印的内容打印在屏幕上

在C语言中,我们通常会见到两类函数:库函数、自定义函数

2. 库函数

我们前面说的 printfscanf 都是库函数,都是已经装好的函数,我们直接使用就可以了

2.1 头文件

要使用这些函数,需要包含它们对应的头文件,如 printfscanf 需要的是 stdio 这个头文件

#include 

2.2 库函数和头文件的查询

库函数还有很多,并不要求我们都能记住,只需要适当的了解就好了,需要的时候再去相应的查询

C/C++官⽅的链接: https://zh.cppreference.com/w/c/header
cplusplus.com: https://legacy.cplusplus.com/reference/clibrary/ 

3. 自定义函数

自定义函数就是我们自己创造出一个属于我们自己的函数,格式如下

type fun_name(形式参数)
{
    语句;
}

这里的 type 可以是整型(int)也可以是浮点型(float)等等,这里的类型表示的是我们最后return 语句返回值的类型,甚至也可以是 void ,没有任何类型,可以不用写return

fun_name是函数名,由自己定义,最好有意义,能够让人记住,方便使用

小括号中是你需要的参数,参数的个数由自己决定

最后在大括号里面加入你需要的语句即可

如果我们要创建一个加法函数

#include 

int Add(int x, int y)
{
    int ret = x + y;
    return ret;
}

int main()
{
    int a = 5;
    int b = 4;
    int c = Add(a,b);
    printf("%d",c);
    return 0;
}
//输出:9

int 为函数下面语句中 return 要返回的类型,ret即为int类型,Add为函数的名字,x,y为参数

因为x,y都是int类型的,所以我们下面主函数main里调用的Add里给的参数ab也是int类型的,要保持一致

最后main里的c的值就为Add函数执行时的返回值

当然Add函数也可以简化为

int Add(int x, int y)
{
    return x + y;
}

3.1 形参和实参

函数中的参数分为形参和实参

3.1.1 形参

形参,也叫形式参数,字面意思来理解就是走个形式的参数而已,这个形参就是上面Add里的 x,y

3.1.2 实参

实参,也叫实际参数,字面意思就是真实存在的参数,我们main函数中传递给Adda、b就是实参

3.1.3 形参和实参之间的关系

main函数的a、b作为参数传递给Add里的x、y的时候,只是将a、b的值传给了x、y,但x、y本身并不是a、b,所以x、y是新开辟出来的地址,a、bx、y的地址是不一样的

所以说,形参是实参的一份临时拷贝

4. 函数的声明

一个函数使用前是需要让main函数知道这个函数的存在的,所以一般我们在定义一个函数的时候都写在main函数的前面

C语言函数的精解_第1张图片

#include 

int Add(int , int );

int main()
{
    int a = 5;
    int b = 4;
    int c = Add(a,b);
    printf("%d",c);
    return 0;
}

int Add(int x, int y)
{
    int ret = x + y;
    return ret;
}

但如果写在了后面呢?

#include 

int Add(int x, int y);

int main()
{
    int a = 5;
    int b = 4;
    int c = Add(a,b);
    printf("%d",c);
    return 0;
}

int Add(int x, int y)
{
    int ret = x + y;
    return ret;
}

如果放在了后面,那么我们需要在main函数前将定义函数的第一行直接复制在main函数的前面,这个就是函数的声明,我们只需要告诉main函数这个Add函数需要的类型就可以了,所以我们还可以这样

#include 

int Add(int , int );

int main()
{
    int a = 5;
    int b = 4;
    int c = Add(a,b);
    printf("%d",c);
    return 0;
}

int Add(int x, int y)
{
    int ret = x + y;
    return ret;
}

5. 多个文件

如果是在企业中,一个项目可能需要多行代码,那么不可能都将所有的东西都放在同一个文件下,所以我们可以放在多个文件中

函数的声明、类型的声明放在头文件 (.h) 中,函数的实现是放在源文件 (.c)

例如刚刚的加法函数:

C语言函数的精解_第2张图片

add.h

add.c

C语言函数的精解_第3张图片

test1.c

C语言函数的精解_第4张图片

但是最好我们可以在我们函数的实现时,加上这么一句代码

包含一下我们自己写的头文件,算是函数的声明了

6. static 和 extern

staticextern 都是C语言中的关键字

static 是静态的的意思

我们可以先来看一段代码

#include 

void test()
{
    int i = 0;
    i++;
    printf("%d ", i);
}

int main()
{
    int i = 0;
    for (i = 0; i < 5; i++)
    {
        test();
    }
    return 0;
}

聪明的你肯定能够知道最后的输出为:1 1 1 1 1

那么如果我们在test函数里的 int i = 0 前面加上个static会发生什么?

#include 

void test()
{
    static int i = 0;
    i++;
    printf("%d ", i);
}

int main()
{
    int i = 0;
    for (i = 0; i < 5; i++)
    {
        test();
    }
    return 0;
}

输出结果为:1 2 3 4 5

从这样的结论我们可以分析出来,当我们第一次进入函数的时候 i 是1,那么再次进入函数的时候 i 怎么就不是1而是2了呢?

因为static i 出函数时 i 并不会被销毁,而是保留了原有的值,所以我们再次进入的时候就进行了累加,所以最后五次的结果就是 1 2 3 4 5 

static修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来是存储在栈区的,但是被static修饰后存储到了静态区,存储在静态区的变量和局部变量是一样的,只有程序结束,变量才销毁,内存才收回

C语言函数的精解_第5张图片

extern是用来声明外部符号的,如果一个全局符号在文件A中定义,想要在文件B中使用,那么我们可以在文件B中使用extern声明,就可以使用文件A中的符号

add.c

test.c

C语言函数的精解_第6张图片

输出结果:

这样就可以在test.c文件中使用add.c中的全局变量了

6.1 static的限制

如果像上面的代码,我们不想让文件B中使用文件A中的符号,那么我们可以使用static限制:

add.c

那么如果这时候编译运行会发生什么?

即使我们在test.c中使用extern也不能使用这个符号了

结论:当被static修饰后,这个符号就只能在本文件内部使用

感谢观看,希望对你有所帮助

---------------------------------------------------------------------------------------------------------------------------------

你可能感兴趣的:(c语言,学习)