C语言中函数与指针的应用总结

 更新时间:2013年05月15日 09:00:27   作者:  
本篇文章是对C语言中函数与指针的应用进行了详细的分析介绍,需要的朋友参考下

1. 首先,在C语言中函数是一种function-to-pointer的方式,即对于一个函数,会将其自动转换成指针的类型.

复制代码 代码如下:

#include<stdio.h>

void fun()
{
}

int main(void)
{
   printf("%p %p %p\n", &fun, fun, *fun);
   return 0;
}


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

这三个值的结果是一样的. 其实对于最后的那个*fun, 即使前面加上很多个*号, 其结果也不变, 即**fun, ***fun的结果都是一样的.
对于这个问题, 因为之前讲过函数是一种function-to-pointer方式, 其会自动转换成指针的类型, &fun是该函数的地址, 为指针类型, fun是一个函数, 会转换成其指针类型, 而对于*fun, 由于fun已经变成了指针类型, 指向这个函数, 所以*fun就是取这个地址的函数, 而又根据function-to-pointer, 该函数也转变成了一个指针, 所以以此类推, 这三个值的结果是相同的.

===================================================
2. 如何调用一个地址上的函数
如果知道了一个函数所在的地址, 可以将其强制转化成某一种类型的函数指针, 然后再根据这个指针去调用这个地址的函数. 如:

复制代码 代码如下:

#include<stdio.h>

void f(int i)
{
   printf("i = %d\n", i);
}

int main(void)
{
   unsigned long add;
   add = (unsigned long)f;
   ((void (*)(int))add)(10);
   (*(void (*)(int))add)(20);
   return 0;
}


---------------------------------------------------------------------------------------
使用(void (*)(int))的方式可以将一个地址转换成一个带int参数且没有返回值的函数的指针类型, 然后再去调用, 由于第1点中讲的function-to-pointer, 所以最后两条语句中加与不加那个*号效果都是一样的. 在嵌入式方面经常用到这种方式.
=====================================================

3. 函数指针数组的用法.
有时候需要定义一个数组, 其内容为一系列的函数指针, 然后对其进行调用, 如:
复制代码 代码如下:

#include<stdio.h>
int max(int v1, int v2)
{
   return (v1 > v2 ? v1 : v2);
}

int min(int v1, int v2)
{
   return (v1 < v2 ? v1 : v2);
}

int sum(int v1, int v2)
{
   return (v1 + v2);
}


复制代码 代码如下:

int main(void)
{
   int (*p[3])(int, int);
   p[0] = max;
   p[1] = min;
   p[2] = sum;

   printf("p[0] = %d\n", (p[0])(3, 5));
   printf("p[1] = %d\n", (p[1])(4, 6));
   printf("p[2] = %d\n", (p[2])(1, 2));
   return 0;
}


-----------------------------------------------------------------------------------------
虽然感觉这种方法有点累赘, 但是也算是一种使用的方式, 所以介绍一下.
============================================

4.返回一个指向数组的指针的方式

可以让函数返回一个指向数组的一个指针, 如:

复制代码 代码如下:

#include<stdio.h>
#include<stdlib.h>
int (*p())[10]
{
   int (*m)[10];
   int i;
   m = (int (*)[10])malloc(10 * sizeof(int));
   if (m == NULL) {
      printf("malloc error\n");
      exit(1);
   }
   for (i = 0; i < 10; i++)
      *(*m+i) = i+1;

   return m;
}

复制代码 代码如下:

int main(void)
{
   int (*a)[10];
   int i;
   a = p();
   for (i = 0; i < 10; i++)
      printf("%d ", *(*a+i));
   printf("\ndone\n");

   return 0;
}


-------------------------------------------------------------------
这种方式中,int (*a)[10]是一个指向一维数组的一个指针, 而p()也是返回一个指向一维数组的一个指针.
===================================================

5.返回一个函数指针的指针

/============================================/
/ 在看到快速排序的例子中使用到返回指针的函数.所以特此查找到这篇文章,觉得很好... /
/============================================/

对这个问题, signal()函数是最好的例子.
void (*signal (int signo, void (*func)(int)))(int);
很多朋友刚开始看这个函数定义的时候是不太懂, 其实可以一步一步地慢慢看, 我以前是这样分析的, 希望能对大家有用.
int (*p)();
这是一个函数指针, p所指向的函数是一个不带任何参数, 并且返回值为int的一个函数.
int (*fun())();
这个式子与上面式子的区别在于用fun()代替了p,而fun()是一个函数,所以说就可以看成是fun()这个函数执行之后,它的返回值是一个函数指针,这个函数指针(其实就是上面的p)所指向的函数是一个不带任何参数,并且返回值为int的一个函数.

所以说signal()可以看成是signal()函数(它自己是带两个参数,一个为整型,一个为函数指针的函数), 而这个signal()函数的返回值也为一个函数指针,这个函数指针指向一个带一个整型参数,并且返回值为void的一个函数.

=================================
signal函数返回的其实是指向以前的信号处理程序的指针, 所以举一个例子来说明返回指向函数的指针的用法.

复制代码 代码如下:

#include<signal.h>
#include<stdlib.h>
#include<stdio.h>

void sig_fun2(int signo)
{
   printf("in sig_fun2:%d\n", signo);
}

void sig_fun1(int signo)
{
   printf("in sig_fun1:%d\n", signo);
}

int main(void)
{
   unsigned long i;
   if (signal(SIGUSR1, sig_fun1) == SIG_ERR) {
      printf("signal fun1 error\n");
      exit(1);
   }

   (signal(SIGUSR1, sig_fun2))(30);

   printf("done\n");
   return 0;
}


====================================================
6. 使用函数指针作为参数的情况 (以前的记录提到过.)
在函数的参数中, 可能会带有一个函数指针, 这在signal()函数中是出现了的.
其实在很多排序函数中就是使用的这个参数为函数指针的方式来进行调用的.比如Quicksort

例如:

复制代码 代码如下:

#include<stdio.h>

int max(int v1, int v2)
{
   return (v1 > v2 ? v1 : v2);
}

int min(int v1, int v2)
{
   return (v1 < v2 ? v1 : v2);
}

int sum(int v1, int v2)
{
   return (v1 + v2);
}

int fun(int a, int b, int (*call)(int, int))
{
   return (call(a, b));
}

int main(void)
{
   printf("max=%d\n", fun(1, 2, max));
   printf("min=%d\n", fun(3, 4, min));
   printf("sum=%d\n", fun(5, 6, sum));
   return 0;
}


相关文章

  • C语言宏函数container of()简介

    C语言宏函数container of()简介

    这篇文章介绍了C语言宏函数container of(),对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • C语言实现餐厅管理系统

    C语言实现餐厅管理系统

    这篇文章主要为大家详细介绍了C语言实现餐厅管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 详解C++ Qt中堆叠窗体的使用案例

    详解C++ Qt中堆叠窗体的使用案例

    这篇文章主要为大家详细介绍了C++ Qt中堆叠窗体的使用案例,文中的示例代码讲解详细,对我们学习QT有一定的帮助,感兴趣的小伙伴可以了解一下
    2023-08-08
  • c++基础使用STL的注意点详解

    c++基础使用STL的注意点详解

    这篇文章主要为大家介绍了c++基础使用STL的注意点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • 利用C语言实现2048小游戏的方法

    利用C语言实现2048小游戏的方法

    2048是比较流行的一款数字游戏,相信对大家来说都不陌生,这篇文章给大家分享了利用C语言实现2048小游戏的方法,对大家学习理解C语言具有一定的参考借鉴价值,有需要的朋友们下面来一起看看吧。
    2016-10-10
  • Qt实现简单TCP服务器

    Qt实现简单TCP服务器

    这篇文章主要为大家详细介绍了Qt实现简单TCP服务器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • java 中ArrayList与LinkedList性能比较

    java 中ArrayList与LinkedList性能比较

    这篇文章主要介绍了java 中ArrayList与LinkedList性能比较的相关资料,需要的朋友可以参考下
    2017-03-03
  • 详解VSCode下C++环境配置过程

    详解VSCode下C++环境配置过程

    这篇文章主要介绍了VSCode C++环境配置过程,在这大家需要在代码的目录下的.vscode文件夹下创建launch.json、tasks.json,具体实现过程跟随小编一起看看吧
    2021-11-11
  • C++二维数组中的查找算法示例

    C++二维数组中的查找算法示例

    这篇文章主要介绍了C++二维数组中的查找算法,结合实例形式分析了C++二维数组进行查找的原理与具体实现技巧,需要的朋友可以参考下
    2017-05-05
  • 一篇文章彻底搞懂C++常见容器

    一篇文章彻底搞懂C++常见容器

    容器就是一些特定类型对象的集合,容器可以分为顺序容器和关联容器,下面这篇文章主要给大家介绍了关于C++常见容器的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02

最新评论