C语言之函数

时间:2021-11-13 01:29:44

函数概论

函数(function)是用于完成特定任务的程序代码的自包含单元。函数具有执行某些动作,或者返回一个值以供程序使用的功能。当然,一个函数可同时具备以上两种功能。我们建议在头文件里面放入一些其他重要的函数和变量,并在主函数里面引入。

一个简单的函数

#include<stdio.h>
#define NUM 50

void starbar(void);  
int main(void)
{
    starbar();
    printf("\nIt's OK!");
    system("pause");
    return 0;
}

void starbar(void)
{
    int i;
    for (i = 1; i <= NUM;i++)
        printf("*");
}

  void starbar(void); 中starbar是函数名,第一个void是表示没有返回值,第二个void表示该函数不接受任何参数。分号表示进行函数的申明而不是函数的定义。

形式参量

 void func(char ch, int num) 中定义了ch和num这两个参数,形式参量是局部变量,可以在其他函数中使用同一个变量名。

不过,ANSI C要求在每一个变量前申明其类型,不能如 void func(int x,y,z) 这样定义。

实际参数

如 func(x,y) 这样调用函数,但是x,y必须是明确的,可以是字符、数字甚至是一个复杂的表达式(必须先计算出表达式)。

黑盒子观点

函数里面所定义的变量都是其私有的局部变量,如果在main()中也有相同名字的变量,它们相互独立,互不影响。如果在main()中存在一个和所定义函数一样的变量,其不会影响到所定义的函数,其余变量也是如此。因此可以认为,黑盒子内的一切操作对调用函数来说都是不可见的。

return返回值

#include<stdio.h>

int min_num(int num1, int num2);

int main(void)
{
    int num_1, num_2;
    printf("Please two integer:\n");
    while ((scanf_s("%d %d", &num_1, &num_2)) == 2) {
        printf("The lessen of those numbers is %d\n", min_num(num_1, num_2));
        printf("Enter anthor integer(any single to quit)\n");
    }
    printf("Bye!\n");
    return 0;
}

int min_num(int num1, int num2)
{
    int res_num;
    if (num1 < num2)
        res_num = num1;
    else
        res_num = num2;
    return res_num;
}

 

在定义函数的开头就用int申明了函数返回的是int类型,就相当于把res_num赋予给了一个int类型的变量。当然,return不仅仅可以返回变量,也可以用 return 表达式 来返回。我们可以把代码改成如下形式:

int min_num(int num1, int num2)
{
    return (num1 < num2) ? num1 : num2;
}

 

return还有一个作用就是终止执行函数,并把控制返回给调用函数的下一个语句。因此,也可以这样改写代码:

int min_num(int num1, int num2)
{
    if (num1 < num2)
        return num1;
    else
        return num2;
}

函数类型与申明

函数应该进行类型申明,同时其类型应该和返回值类型相同,而无返回值的函数应该被申明为void类型。

为正确的使用函数,程序在首次调用函数之前需要知道该函数的类型。第一种途径就是在调用函数之前进行完整的函数定义,另一种途径就是在函数调用之前预先申明被调用函数的类型。

ANSI C的函数原型

ANSI C标准使用函数原型来申明返回值类型、参数个数以及各参数的类型。我们可以通过下面的任意一个进行申明:

int func(int,int);
int func(int a,int b); //当然,其中的a和b可以不用和定义函数时所用的一样。

递归

#include<stdio.h>

void up_and_down(int);

int main(void)
{
    up_and_down(1);
    system("pause");
    return 0;
}

void up_and_down(int n)
{
    printf("Level %d: n location %p\n", n, &n);
    if (n < 4) {
        up_and_down(n + 1);
        printf("LEVEL %d: n location %p\n", n, &n);
    }
}

/*result:

Level 1: n location 012FF8E8
Level 2: n location 012FF810
Level 3: n location 012FF738
Level 4: n location 012FF660
LEVEL 3: n location 012FF738
LEVEL 2: n location 012FF810
LEVEL 1: n location 012FF8E8

*/

 尾递归

就是把递归调用的语句放在函数结尾即恰在return语句之前,就称为尾递归或结尾递归。

#include<stdio.h>
long fact(int n);
long rfact(int n);

int main(void)
{
    int num;
    printf("Enter a number(0-12):");
    while (scanf_s("%d", &num) == 1) {
        if (num < 0)
            printf("Sorry,I can't accpet a negative number!");
        else if (num > 12)
            printf("Keep input under 12");
        else
        {
            printf("Loop: %d factorial = %ld\n", num, fact(num));
            printf("Recursion: %d factorial = %ld\n", num, rfact(num));
        }
        printf("Enter a number(0-12):");
    }
    printf("Bye!");
    return 0;
}

long fact(int n) //循环方式
{
    long ans;
    for (ans = 1; n > 1; n--)
        ans *= n;
    return ans;
}

long rfact(int n) //递归方式
{
    long ans;
    if (n > 0)
        ans = n*rfact(n - 1);
    else
        ans = 1;
    return ans;
}

 斐波拉契数列

该数列采用双重递归。

long Fibonacci(int n)
{
    if (n > 2)
        return Fibonacci(n - 1)*Fibonacci(n - 2);
    else
        return 1;
}

地址运算符:&

当需要改变调用函数中的某个数值时,任何被调用的无返回值的C函数都需要使用地址参数来完成该任务。在C语言中,每个函数里面的变量都使用自己的地址。

一元运算符&

一元运算符&可以取得变量的存储地址。

int n = 12;
printf("%d  %p", n, &n);
/*
12  00DCFD6C
*/

 

 指针简介

指针是一个其数值为地址的变量(或更一般地说是一个数据对象)。如果将某个指针变量命令为ptr,就可以使用 ptr=&pooh; 并称其为ptr“指向”pooh。

间接运算符

想要把指针命令为可以存放一个int数值的地址,就需要使用该新的运算符。

years = 10;
ptr = &years; /*指向years的指针*/
val = *ptr;  /*将ptr指向的值赋给val*/

 

申明指针

int *pi;              //pi是指向一个整数变量类型的指针
char *pc;          //pc是指向一个字符变量类型的指针
float *pf,*pg;    //pf和pg是指向浮点变量类型的指针

 

pc等的值是一个地址,在大多数情况下,它由一个无符号整数表示。但是,这并不能表示可以把整数看成整数类型。一些处理数据的方法不能用来处理指针。