函数指针,才是一切一切的根基

2023-12-05 09:38
文章标签 函数指针 根基

本文主要是介绍函数指针,才是一切一切的根基,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.  前言

最近工作中,在干一件事情,就是打通从安卓的java代码,到JNI,最后到server端的C代码。

当然这个过程,早已有大神们做好了,我只是根据当前的业务需要,定制化的实现这个过程。

那这和函数指针,有啥关系呢?请先看程序和内存的关联关系。


2.  C语言中的内存布局

C语言的内存布局[1], 如下图所示


任何一个C语言可执行程序,以有组织的方式加载到计算机内存当中,这段内存被称为进程地址空间或者C程序的内存布局。


通常,将这个内存布局,分为如下几个部分:

(1)Text segment  ——文本段

文本段包含C程序的可执行指令,也称为代码段。文本段是不同的进程之间可共享的

(2)Data segment —— 数据段

这里分为2个子段:初始化数据段和未初始化数据段。通俗的说,不为0的全局变量和静态变量,会存储在初始化数据段。其余的变量会存储在未初始化数据段。

(3)Heap segment —— 堆

在堆区,我们可以动态的开辟和释放内存。开辟内存可以使用malloc(), calloc(), realloc() and new for C++。释放内存可以使用free() or delete。

(4)Stack segment —— 栈

所有函数当中声明的变量,会存储在栈区,存储内容也包括地址,形参等信息。当我们调用某个函数,会创建一个stack frame,当函数返回之后,stack frame将会被销毁。stack pointer将会记录所有的出栈,入栈信息。

每一个函数都拥有自己的stack frame,当调用函数时,stack frame的结构图如下:


(5)Unmapped or reserved —— 预留段

未映射或预留段包含命令行参数和其他程序相关数据,如可执行映像的较低地址,较高地址等。


3.  函数指针

(1)函数指针:指向函数地址的指针。

A function pointer is a pointer that refers to the address of a function.

一个典型的函数指针,如下:

int (*func)(int a, float b);

(2)函数指针的例子[2]——异步调用

demo1 : 

/ * This code catches the alarm signal generated from the kernelAsynchronously */
#include <stdio.h>
#include <signal.h>
#include <unistd.h>struct sigaction act;/* signal handler definition goes here */
void sig_handler(int signo, siginfo_t *si, void *ucontext)
{printf("Got alarm signal %d\n",signo);/* do the required stuff here */
}int main(void)
{act.sa_sigaction = sig_handler;act.sa_flags = SA_SIGINFO;/* register signal handler */sigaction(SIGALRM, &act, NULL);  /* set the alarm for 10 sec */       alarm(10);   /* wait for any signal from kernel */                                        pause();  /* after signal handler execution */                                             printf("back to main\n");                     return 0;
}




demo2:

/* insertion_sort.h */typedef int (*callback)(int, int);
void insertion_sort(int *array, int n, callback comparison);

/* insertion_main.c */#include<stdio.h>
#include<stdlib.h>
#include"insertion_sort.h"int ascending(int a, int b)
{return a > b;
}int descending(int a, int b)
{return a < b;
}int even_first(int a, int b)
{/* code goes here */
}int odd_first(int a, int b)
{/* code goes here */
}int main(void)
{int i;int choice;int array[10] = {22,66,55,11,99,33,44,77,88,0};printf("ascending 1: descending 2: even_first 3: odd_first 4: quit 5\n");printf("enter your choice = ");scanf("%d",&choice);switch(choice){case 1:insertion_sort(array,10, ascending);break;case 2:insertion_sort(array,10, descending);case 3:insertion_sort(array,10, even_first);break;case 4:insertion_sort(array,10, odd_first);break;case 5:exit(0);default:printf("no such option\n");}printf("after insertion_sort\n");for(i=0;i<10;i++)printf("%d\t", array[i]);printf("\n");return 0;
}

/* insertion_sort.c */#include"insertion_sort.h"void insertion_sort(int *array, int n, callback comparison)
{int i, j, key;for(j=1; j<=n-1;j++){key=array[j];i=j-1;while(i >=0 && comparison(array[i], key)){array[i+1]=array[i];i=i-1;}array[i+1]=key;}
}


从以上2个demo,已经可以很明显的看出函数指针的用途和用法。

不过,这和开始说的,函数指针是一切的根基,好像毫无关联啊,怎么看都是一种编程技巧嘛。

别急,往下看。


4.  再探内存地址和程序的关系

有人曾经说过,c语言的精华是指针,我认为这句话没有说完,c语言的精华是函数指针才对。

为什么这么说?

既然,程序只不过是内存的一部分。而函数是程序的一部分。

那换句话说,其实程序就是计算机按照一定顺序访问内存地址的过程。

那么,只要能够控制(获取)内存地址,就等于掌握了计算机。

说到这里,函数指针的意义已经很明确了。


那么,安卓的java代码,与JNI的C代码,再到server的C代码,到底怎么交互呢?

很简单,互相传递函数指针,一切搞定!




参考文献:

[1]http://www.firmcodes.com/memory-layout-c-program-2/

[2]http://opensourceforu.com/2012/02/function-pointers-and-callbacks-in-c-an-odyssey/



这篇关于函数指针,才是一切一切的根基的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/457049

相关文章

C++函数对象与函数指针不同之处

在C++编程语言中,有很多功能都与C语言相通,比如指针的应用等等。在这里我们介绍的则是一种类似于函数指针的C++函数对象的相关介绍。C++函数对象不是函数指针。但是,在程序代码中,它的调用方式与函数指针一样,后面加个括号就可以了。这是入门级的随笔,说的是函数对象的定义,使用,以及与函数指针,成员函数指针的关系。 C++函数对象实质上是一个实现了operator()--括号操作符--的类。 下面是函

C/C++:函数指针

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 引言函数指针的概念函数指针的实现C语言实现C++实现 函数指针的应用 引言 我们之前学过各种各样指针,今天我们来讨论一下函数指针 我们先分析C和C++不同定义函数指针的方式,然后进一步探讨函数指针的应用。 函数指针的概念 函数指针是一种特殊的指针,它指向的不是变量地址,而是函数的地址

C语言指针进阶二:(函数指针数组,转移表)

函数指针数组 函数指针数组就是存放函数指针的一个数组,数组里都是函数指针,那么该怎么定义:   int (*parr[10])(); 因为 [] 的优先级高于 * ,所以parr先与 [] 结合说明是一个数组,元素类型是 int(*)() 的函数指针。 函数指针数组的用途:转移表 转移表的基础列子:实现计算器 #include<stdio.h>//函数指针数组创建的简易计算器,又称转

一个函数指针的注册单例类

class RegisterClass {public:typedef string(*Creator) (const string);typedef map <string, Creator> CreatorResgister;static CreatorResgister& Registry() {static CreatorResgister* g_ = new CreatorResgis

函数指针变量与指针型函数区别

函数指针变量定义的一般形式: 类型说明符 (*指针变量名)() 其中,“类型说明符”表示被指函数的返回值类型。“(*指针变量名)”表示*后面的变量是定义的指针变量。最后的空括号表示指针变量所指的是一个函数。 例如:int (*pf)();表示pf是一个指向函数入口的指针变量,该函数的返回值是整形。   指针型函数的一般形式: 类型说明符 *函数名(形参列表){………………} 其中函数

指针函数、函数指针与递归函数

一.指针函数 1.定义         指针函数是一个函数,其返回值是一个指针         例如:                 void *function()                 int *function()                 float *function() 2.指针函数的返回值         指针函数的返回值要求是 全局变量的地址/st

关于调用子函数给主函数指针分配内…

典型的错误例子如下 在这个主函数的指针给子函数传递一个指针,而在子函数中形参有开辟了一块内存,此子函数的指针的内存里存储的地址与主函数是同一地址,即主函数的指 针和子函数形参的指针都指向同一块内存的地址,但是在子函数里,为子函数的指针申请了一块空间,并不影响主函数的指针。因为子函数的指针又指向了别的内 存。要想分配成功就得用下面两个例子。一个是在子函数的形参中第一指向指针的指针即二级指针,

C语言头文件组织与包含原则(函数指针和结构体的前项声明)

http://jingpin.jikexueyuan.com/article/38309.html 在实际编程中,常常因头文件包含不当而引发编译时报告符号未定义的错误或重复定义的警告。要消除符号未定义的编译错误,只需在引用符号(变量、函数、数据类型及宏等)前确保它已被声明或定义[4]。要消除重复定义的警告,则需合理设计头文件包含顺序和层次  头文件的

详解C/C++函数指针声明

转自: http://www.cnblogs.com/iuices/archive/2011/11/21/2257710.html  要理解一个C程序,仅仅理解组成该程序的符号是不够的。程序员还必须理解这些符号是如何组合成声明、表达式、语句和程序的。      我们先来看看下面的一个语句: 1 ( *( void (*)())0)();

指针函数、函数指针、回调函数

最近在看nginx方面的知识,在看到nginx块的时候,在nginx模块这个结构体中有7个函数指针。因为最近一年都在做java C语言的知识都没怎么用,今天既然遇到了,那么久查查资料再理解一下吧。 1、指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针      类型标识符    *函数名(参数表)       float *func(x,y); 首先