C语言----指针与函数(高阶篇三十三)

 

  传值与传址

    父函数如果将变量的钥匙复制一份,再传给子函数,子函数就可以用钥匙开启这个变量,来进行操作。C语言中这种做法叫“传递指针”。

    程序1

      传址演示:设计一个函数,它可以交换任意两个变量的值。

// 33-1设计一个函数,它可以交换任意两个变量的值.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。


#include <stdio.h>
void swap(int *a1,int *a2)   //交换函数
{
    int temp;
    temp = *a1;
    *a1 = *a2;
    *a2 = temp;
}

main()
{
    //输入两个整数
    int a, b;
    scanf("%d%d", &a, &b);
    //int *p1 = &a, *p2 = &b;
    swap(&a, &b);
    //swap(p1, p2);
    printf("%d\n%d\n", a, b);
}

 

  scanf与&

    假设scanf函数定义如下:

 

      void scanf(int *p1,int *p2)

 

      {

 

        *p1=从键盘读值;

 

        *p2=从健盘读值;

 

      }

      main()

      {

        int a,b;

        scanf(&a,&b);

        printf("%d,%d",a,b);

      }

 

     

    printf为什么不用加&

      void printf(int a,int b)

      {

        屏幕显示=a;

        屏幕显示=b;

      }

 

      main()

      {

        int a,b;

        printf(a,b);

      }

  数组名做函数参数

    程序2

      数组名做函数参数

// 33-2数组名做函数参数.c
#include <stdio.h>

//函数形参规定int arr[] 与 int arr[3]  与 int *arr意义是相同的
//int 表示数组元素个数
int sum(int *arr, int n)   //操作数组时,定义形参: 数组名    数组元素个数
{
    int i = 0, s = 0;  //计数器 总和
    for ( ;i<n;i++)
    {
        s = s + *(arr + i);
    }
    return s;
}

main()
{
    int a[3] = {1,2,3};
    printf("%d\n", sum(a, 3));
}

    注意:

      ※父子函数传递数组时,人们最先想到是使用

      这样的方式传递:

      fun(b[n]){…}

      main()

      {

        int a[10];

        fun(a[10]);

      }

    这是错误的理解。

 

    ※C语言规定:在函数的形式参数中,一旦发现int arr[]或int arr[3]这种数据类型定义,就统一编译为int *arr

    因此,向子函数传递整个数组时,一定要附加一个参数来传递数组元素个数int n,定义成int arr[3]没有用,父函数照样可以传递一个int a[100]或是int a[2]进去。

 

    ※用数组名做参数有2个巨大的好处:

      (1)再大的数组,只要传递2个参数,大大提高编程效率

      (2)子函数不用返回值也可以批量修改父函数中的数据,真正做到“内存共享”。子函数相当于不用return,就可以返回值给父函数,还同时返回多个值。

      因此,在函数间传递数组名,是经常使用的方法。

 

  函数指针和函数返回指针

    函数指针和函数返回指针这两种定义的区别:

 

        函数指针(也叫指向函数的指针):

          int  (*pf)(int a);        /*注意分号   int  pf(int a);  */ 

 

        函数返回指针(也叫返回地址的函数),它的定义形式为:

          int* fun(int a){…}

 

    程序3

      用函数找出一个数组中的最大数,返回它的地址

// 33-3用函数找出一个数组中的最大数,返回它的地址.c 

#include <stdio.h>
int *find(int *arry,int n)    //定义函数返回指针
{
    int *pmax;   
    pmax = arry;    // 数组首地址赋给 指针pmax
    for (int i = 1; i < n; i++)
    {
        if (*(arry + i) > *pmax)   //比较值
            pmax = arry + i;     //赋值地址
    }
    return pmax;   //返回地址
}



main()
{
    int a[4] = { 15,67,89,13 };    //定义一个数组
    int *pa = find(a,4);
    printf("%d\n", *pa);
}

  类型分解

    ※类型定义符出现在不同的标识符前,所表达的含义不同:

      int i

    出现在变量前,表示定义整型变量

      int fun()

    出现在函数前,表示函数返回int

      int a[10]

    出现在数组前,表示数组的每个元素都是整型

      int *p

    出现在指针前,表示定义的指针是整型

    ※变量之间通过指针或结构赋值或函数间传递参数时,类型必须相同,否则编译无法通过。

    像int a;这样的类型定义,较好理解,表示a为int型,若是遇到复杂的类型,我们可以先找到变量或函数在程序头部的定义,将它的名称删除,就是它的类型。

 

    下面几个是容易混淆的定义:

      int* fun()           类型为int* ()

      int *a[10]          类型为int*[10]

      int (*pf)()          类型为int(*)()

      int (*b)[10]         类型为int(*)[10 ]

  练习

    1、请编写函数,对传送过来的三个数选出最大和最小数,并通过形参传回调用函数。

 

// 33-4对传送过来的三个数选出最大和最小数,并通过形参传回调用函数.c


#include <stdio.h>

void fun(int a,int b,int c,int *nmax, int *nmin)
{
    *nmax = a;
    if (b > *nmax) *nmax = b;
    if (c > *nmax) *nmax = c;

    *nmin = a;
    if (b < *nmin) *nmin = b;
    if (c < *nmin) *nmin = c;
}

main()
{
    int a, b, c,m,n;
    scanf("%d%d%d", &a, &b, &c);
    fun(a,b,c,&m,&n);  //传入 m n 的地址
    printf("最大值%d\n最小值%d\n", m, n);

}

 

    2、请编写函数,其功能是对传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数。

// 传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数.c

#include <stdio.h>

//浮点数求和。  求差值。

void fun( float *sum , float *diff)
{
    float a, b;
    a = *sum; b = *diff;
    *sum = a + b;
    *diff = a - b;

}

main()
{
    float a, b;
    scanf("%f%f", &a, &b);
    fun(&a, &b);
    printf("和:%f\n差:%f\n", a, b);
}

 

posted @ 2021-11-11 22:05  httpcc  阅读(306)  评论(0编辑  收藏  举报