{译}函数指针漫谈(2)

漫谈C语言指针(三) 上一篇漫谈C语言指针(二) 主要讲了指针和数组的关系、字符串指针、指针变量作为函数参数,就像电影最后进入高潮一样,接下来,指针的内容将进入深水区,大家坐稳扶好,马上出发~ 今天要讲的内容有:二级指针、二维数组、指针数组、函数指针、函数指针数组、结构体指针。为什么说的深水区呢?因为前面的2篇只要看懂概念基本就能学会,但是这一章,概念开始变绕,不再平坦,甚至有点花俏,所以需要消费一些脑细胞才可以理解,不过不用担心,我对我的表达有自信(看不懂也勿喷。。) 二级指针 二级指针,顾名思义,就是指针的指针,一个指针指向 阅读详情

C/C++函数指针的语法

http://blog.youkuaiyun.com/luckheadline
1. 定义函数指针
    有两种函数指针类型:一个是C函数指针或静态C++成员函数指针;另外一个是非静态的C++成员函数指针。基本的区别是所有的非静态成员函数指针都需要一个隐藏参数:this指针是一个类的实例。记住:这两种函数指针彼此不兼容。
    因为函数指针只是一个变量,因此它必须被定义。在下面例子里我们定义了三个函数指针pt2Function, pt2Member and pt2ConstMember。他们都有三个参数(一个float型,两个char型),返回都是int型。在假定的C++例子里,这些函数都是TMyClass的非静态成员函数。
// 2.1 define a function pointer and initialize to NULL
int (*pt2Function)(float, char, char) = NULL;                        // C
int (TMyClass::*pt2Member)(float, char, char) = NULL;                // C++
int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;     // C++

2. 调用约定(Calling Convention)
通常你没必要考虑函数的调用约定:如果你没有特别指定,编译器缺省会假定为__cdecl。调用约定会告诉编译器诸如如何传递参数或者怎样产生函数名。其它的调用约定有__stdcall, __pascal and __fastcall。调用约定属于函数签名:因此不同调用约定的函数和函数指针彼此不兼容!对于Borland和Microsoft编译器,我们要在返回类型和函数或者函数指针名之间指明具体的调用约定。对于GNU GCC,我们使用__attribute__关键字。
// 2.2 define the calling convention
void __cdecl DoIt(float a, char b, char c);                             // Borland and Microsoft
void         DoIt(float a, char b, char c)  __attribute__((cdecl));     // GNU GCC

3. 为函数指针分配地址
    很容易就可以将一个函数的地址分配给一个函数指针。我们就简单的使用一个合适的已知函数或成员函数的名字,但是对大多数编译器我们可以选择在函数名前加上取地址符&。我们可能需要使用成员函数完整的名字,包括类名和域操作符(::)。而且,我们需要保证访问的函数确实在可以访问的域里。
// 2.3 assign an address to the function pointer
//     Note: Although you may ommit the address operator on most compilers
//     you should always use the correct way in order to write portable code.

// C
int DoIt  (float a, char b, char c){ printf("DoIt/n");   return a+b+c; }
int DoMore(float a, char b, char c)const{ printf("DoMore/n"); return a-b+c; }

pt2Function = DoIt;      // short form
pt2Function = &DoMore;   // correct assignment using address operator

// C++
class TMyClass
{
public:
   int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
   int DoMore(float a, char b, char c) const
         { cout << "TMyClass::DoMore" << endl; return a-b+c; };

   /* more of TMyClass */
};

pt2ConstMember = &TMyClass::DoMore; // correct assignment using address operator
pt2Member = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore

4. 比较函数指针
    我们同样可以使用比较运算符(==, !=)。下面的例子是检查是否函数pt2Function和pt2Member实际包含了函数DoIt和TMyClass::DoMore的地址。
// 2.4 comparing function pointers
// C
if(pt2Function >0){                           // check if initialized
   if(pt2Function == &DoIt)
      printf("Pointer points to DoIt/n"); }
else
   printf("Pointer not initialized!!/n");

// C++
if(pt2ConstMember == &TMyClass::DoMore)
   cout << "Pointer points to TMyClass::DoMore" << endl;

5. 使用函数指针调用函数
    C语言中,通过显式的用*运算符去引用可以调用一个函数。同样你也可以使用函数指针的名字而不是函数名。在C++中,操作符.*和.->*与类的实例一起以调用成员函数。如果调用发生在另一个成员函数中,我们可以使用this指针。
// 2.5 calling a function using a function pointer
int result1 = pt2Function    (12, 'a', 'b');          // C short way
int result2 = (*pt2Function) (12, 'a', 'b');          // C

TMyClass instance1;
int result3 = (instance1.*pt2Member)(12, 'a', 'b');   // C++
int result4 = (*this.*pt2Member)(12, 'a', 'b');       // C++ if this-pointer can be used

TMyClass* instance2 = new TMyClass;
int result4 = (instance2->*pt2Member)(12, 'a', 'b');  // C++, instance2 is a pointer
delete instance2;

6. 如何将函数指针当作参数传递
    我们可以将函数指针作为函数的一个参数传递,特别如果想要传递一个指针作为callback函数。下面的代码表明如何传递一个指针给函数,函数有一个float型参数和两个char型参数,返回int型:
//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer
// <pt2Func> is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
{
   int result = (*pt2Func)(12, 'a', 'b');     // call using function pointer
   cout << result << endl;
}

// execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
void Pass_A_Function_Pointer()
{
   cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
   PassPtr(&DoIt);
}

7. 如何返回函数指针
    这个会有点微妙但一个函数指针是可以作为一个函数的返回值的。下面的例子中有两个解决方案关于如何返回一个函数指针,它有两个float型参数并返回float型。如果想返回一个成员函数指针,我们不得不改变所有函数指针的定义/声明。
//------------------------------------------------------------------------------------
// 2.7 How to Return a Function Pointer
// 'Plus' and 'Minus' are defined above. They return a float and take two float
// Direct solution: Function takes a char and returns a pointer to a
// function which is taking two floats and returns a float. <opCode>
// specifies which function to return
float (*GetPtr1(const char opCode))(float, float)
{
   if(opCode == '+')
      return &Plus;
   else
      return &Minus; // default if invalid operator was passed
}

// Solution using a typedef: Define a pointer to a function which is taking
// two floats and returns a float
typedef float(*pt2Func)(float, float);

// Function takes a char and returns a function pointer which is defined
// with the typedef above. <opCode> specifies which function to return
pt2Func GetPtr2(const char opCode)
{
   if(opCode == '+')
      return &Plus;
   else
      return &Minus; // default if invalid operator was passed
}

// Execute example code
void Return_A_Function_Pointer()
{
   cout << endl << "Executing 'Return_A_Function_Pointer'" << endl;

   // define a function pointer and initialize it to NULL
   float (*pt2Function)(float, float) = NULL;

   pt2Function=GetPtr1('+');   // get function pointer from function 'GetPtr1'
   cout << (*pt2Function)(2, 4) << endl;   // call function using the pointer

   pt2Function=GetPtr2('-');   // get function pointer from function 'GetPtr2'
   cout << (*pt2Function)(2, 4) << endl;   // call function using the pointer
}

8. 如何使用函数指针数组
    操作函数指针数组非常有趣。它提供了选择一个函数作为索引的可能。它的语法很难,经常容易导致疑惑。下面是两种如何在C/C++中定义和使用函数指针数组的方式。第一种是使用typedef,第二种直接定义数组。实际中可以选择自己偏好的方式。
//------------------------------------------------------------------------------------
// 2.8 How to Use Arrays of Function Pointers

// C ---------------------------------------------------------------------------------

// type-definition: 'pt2Function' now can be used as type
typedef int (*pt2Function)(float, char, char);

// illustrate how to work with an array of function pointers
void Array_Of_Function_Pointers()
{
   printf("/nExecuting 'Array_Of_Function_Pointers'/n");

   // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are arrays
   // with 10 pointers to functions which return an int and take a float and two char

   // first way using the typedef
   pt2Function funcArr1[10] = {NULL};

   // 2nd way directly defining the array
   int (*funcArr2[10])(float, char, char) = {NULL};


   // assign the function's address - 'DoIt' and 'DoMore' are suitable functions
   // like defined above in 2.1-4
   funcArr1[0] = funcArr2[1] = &DoIt;
   funcArr1[1] = funcArr2[0] = &DoMore;

   /* more assignments */

   // calling a function using an index to address the function pointer
   printf("%d/n", funcArr1[1](12, 'a', 'b'));         //  short form
   printf("%d/n", (*funcArr1[0])(12, 'a', 'b'));      // "correct" way of calling
   printf("%d/n", (*funcArr2[1])(56, 'a', 'b'));
   printf("%d/n", (*funcArr2[0])(34, 'a', 'b'));
}


// C++ -------------------------------------------------------------------------------

// type-definition: 'pt2Member' now can be used as type
typedef int (TMyClass::*pt2Member)(float, char, char);

// illustrate how to work with an array of member function pointers
void Array_Of_Member_Function_Pointers()
{
   cout << endl << "Executing 'Array_Of_Member_Function_Pointers'" << endl;

   // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are
   // arrays with 10 pointers to member functions which return an int and take
   // a float and two char

   // first way using the typedef
   pt2Member funcArr1[10] = {NULL};

   // 2nd way of directly defining the array
   int (TMyClass::*funcArr2[10])(float, char, char) = {NULL};


   // assign the function's address - 'DoIt' and 'DoMore' are suitable member
   //  functions of class TMyClass like defined above in 2.1-4
   //nd use an array of function pointers in C and C++. The first way uses a typedef, the second way directly defines the array. It's up to you which way you prefer.

   funcArr1[0] = funcArr2[1] = &TMyClass::DoIt;
   funcArr1[1] = funcArr2[0] = &TMyClass::DoMore;
   /* more assignments */

   // calling a function using an index to address the member function pointer
   // note: an instance of TMyClass is needed to call the member functions
   TMyClass instance;
   cout << (instance.*funcArr1[1])(12, 'a', 'b') << endl;
   cout << (instance.*funcArr1[0])(12, 'a', 'b') << endl;
   cout << (instance.*funcArr2[1])(34, 'a', 'b') << endl;
   cout << (instance.*funcArr2[0])(89, 'a', 'b') << endl;
}

WPS JS宏实战:批量调整200个Word表格格式的避坑指南(附完整代码) 本文提供了一份详尽的WPS JS宏实战指南,针对批量调整大量Word表格格式的需求。文章深入解析了如何利用JS宏自动化设置字体、行距和边框,并重点解决了常见的“首行访问报错”等核心难题,附有可直接使用的完整代码,帮助用户显著提升文档处理效率。 阅读详情

相关推荐

SIwave学习记录:电热耦合仿真

SIwave电热耦合仿真

m0_68174736的博客 2336

{译}函数指针漫谈(1)

http://blog.youkuaiyun.com/luckheadline    函数指针是一种有趣,有效而又优雅的编程技术。我们可以使用它来替换switch/if语句以达到晚绑定或callback的目的。然后,由于它的语法复杂, 因此在大多数的书和文档中都提及较少或者讲述的非常简短和肤浅。比起通常指针,它们并不易出错。我们需要做的只是理解它们是什么并且学习他们的语法。但要务必记住问问自己是否真正

双子星 -- Focus on Algorithm, System Design and Computer Graphics. 535

DrMOS电路仿真

将驱动电路与功率MOS集成化后既是DrMOS。把驱动芯片以及上下桥MOSFET封装在一起,这样每一相供电就有了单独的驱动芯片,并且这种高度整合的MOSFET可以通过更高的电流、发热比传统的MOSFET也小很多且更节能 自举升压同步BUCK高低侧栅驱动电路原理及仿真 ...

Srambler的博客 5040

{译}函数指针漫谈(3)

在C/C++中如何实现callbackhttp://blog.youkuaiyun.com/luckheadline1. callback函数概念    函数指针提供了callback函数的概念。如果你不确信如何使用函数指针,请参见这系列前面的部分。我通过著名的排序函数qsort来介绍callback函数的概念。这个函数将根据用户指定的rank规则对一个域中的元素进行排序。这个域可以包含任何类

双子星 -- Focus on Algorithm, System Design and Computer Graphics. 652

顶刊级科研绘图技巧

顶刊级科研绘图技巧

2401_89571885的博客 1157

一文吃透 SAP HANA JSON Document Store:从架构到实战的完整指南

本文详细介绍了SAP HANA的JSON Document Store功能,包括其定位、架构、典型场景以及具体使用方法。文章首先分析了半结构化数据场景下传统关系模型的局限性,说明Document Store如何通过集合(Collection)存储JSON文档来提供灵活性。随后详细阐述了启用方式、SQL语法、与Column Store的联动机制,并提供了大量可直接复用的实战案例。特别强调了Document Store作为HANA内建服务的优势,包括企业级一致性、备份恢复等能力。最后给出了数据类型处理和跨引擎协

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 201

{译}函数指针漫谈(4)

使用仿函数封装C和C++函数指针http://blog.youkuaiyun.com/luckheadline1. 什么是仿函数    仿函数是带有状态的函数。在C++中,可以认为它们是带有一个或多个存储有状态的私有成员和带有个一个重载操作符()以执行函数的类。仿函数可以使用模板和多态的概念封装C和C++函数指针。我们可以为任意类建立一个成员函数指针列表,然后通过相同的接口调用它们而不影响它们

双子星 -- Focus on Algorithm, System Design and Computer Graphics. 548

NXP S32k3 MCAL EMIOS PWM配置

NXP s32k 配置 EMIOS PWM

Leon_0125的博客 2702

c语言漫函数,杨宗德漫谈C语言函数指针

杨宗德漫谈C语言函数指针:一、函数指针的定义顾名思义,函数指针就是函数的指针。它是一个指针,指向一个函数。看例子:A)char * (*fun1)(char * p1,char * p2);B)char * *fun2(char * p1,char * p2);C)char * fun3(char * p1,char * p2);看看上面三个表达式分别是什么意思?C):这很容易,fun3 是函数名...

weixin_26843605的博客 292

搭建一个简单的 Django + Vue 项目

在本文中,我将为您详细介绍如何搭建一个简单的 Django + Vue 项目。Django 是一个使用 Python 编写的高级 Web 框架,而 Vue 是一个流行的 JavaScript 框架,用于构建用户界面。通过结合 Django 和 Vue,我们可以创建强大的全栈 Web 应用程序。创建 Django 项目设置 Django 后端创建 Vue 前端连接 Django 和 Vue让我们开始吧!

JfpBlockchain的博客 352

VTK实战完整教程介绍

该专栏以VTK提供的Example为基础,讲解VTK中的相关接口和使用方法。订阅该专栏,带你了解所有VTK的功能,以便VTK更好的解决工作中遇到的问题。一起学习起来吧!

qq_40041064的博客 2506

c 语言传函数指针有什么用,漫谈C指针:函数指针作为函数参数使用

既然函数指针变量是一个变量,当然也可以作为某个函数的参数来使用的。所以,你还应知道函数指针是如何作为某个函数的参数来传递使用的。一个实例:要求:我要设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的定义格式应相同)。实现:代码如下:#include "stdio.h"/* 自行包含头文件 */void...

weixin_36364707的博客 256

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

c 语言函数指针定义,漫谈C指针:定义函数的指针类型

就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来声明函数指针变量。我先给你一个自定义数据类型的例子。#include "stdio.h"typedef int* PINT; /* 为int* 类型定义了一个PINT的别名*/int main(){int x;PINT px = &x; /* 与“int *px=&x;”是等价的。PINT类型其实就是int...

weixin_30425639的博客 541

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

《C指针漫谈:那个让你又爱又恨的家伙》(空指针、野指针、void 指针(万能指针)、函数指针、指针数组、数组指针)

本文主要讲解指针的多种用法,和一些概念,不过多赘述一些函数的用法,全文5400多字,根据需要查漏补缺, 如有疑问可以随时私信,会第一次时间进行更新补充和说明形而上学者谓之道,形而下学者谓之器目录前言一、指针的基本概念二、指针类型和指针运算三、多级指针四、万能指针五、野指针六、悬垂指针七、空指针八、指针和数组九、指针数组和数组指针十、指针和字符数组十一、指针和动态内存 堆和栈十二、动态内存函数 malloc calloc relloc 和free的使用十三、内存泄露十四、函数返回指针。

qq_63561301的博客 835

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

漫谈C指针第十八讲---函数指针作为函数参数使用

转自:http://www.nowamagic.net/librarys/veda/detail/2136既然函数指针变量是一个变量,当然也可以作为某个函数的参数来使用的。所以,你还应知道函数指针是如何作为某个函数的参数来传递使用的。一个实例:要求:我要设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的

爱橙子的OK绷的专栏 479

C语言之漫谈指针(下)

C语言之漫谈指针(下)优惠券 https://m.fenfaw.cn/ 在上节我们讲到了一些关于指针的基础知识: 详见:C语言之漫谈指针(上) 本节大纲: 零.小tips 一.字符指针 二.指针数组与数组指针 三.数组传参与指针传参 四.函数指针及函数指针数组 五.回调函数 六.例题讲解 零.小tips 在正式开始下节之前,我们先来穿插两个小tips: 1.打印函数哪家强! //假设有下面两个打印函数,我们应该首选哪个? struct person { char name[20]; ..

weixin_48967543的博客 184

【漫谈C语言和嵌入式013】函数指针与指针函数详解:概念、区别及实例

在C语言中,理解指针的各种用法是非常关键的,特别是当涉及到更复杂的概念如函数指针和指针函数时。这两者听起来非常相似,但实际上是完全不同的概念。在这篇博客中,我们将探讨函数指针和指针函数的定义、区别以及如何在实际中使用它们。

2403_83044722的博客 522

漫谈C指针第十六讲---函数调用的指针写法

通过函数指针变量调用函数有了FunP指针变量后,我们就可以对它赋值指向MyFun,然后通过FunP来调用MyFun函数了。看我如何通过FunP指针变量来调用MyFun函数的:/* 自行包含头文件 */ void MyFun(int x); /* 这个声明也可写成:void MyFun( int )*/ void (*FunP)(int ); /*也可声明成void(*FunP)(int x),但习惯

爱橙子的OK绷的专栏 549

漫谈C指针第十五讲---函数名其实也是指针

一般的函数调用一个通常的函数调用的例子:/* 自行包含头文件 */ void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */int main(int argc, char* argv[]) { MyFun(10); /* 这里是调用MyFun(10) 函数 */ return(0); }void MyFun(int x) /* 这里定义一个

爱橙子的OK绷的专栏 580

《 C++ 点滴漫谈: 三十三 》当函数成为参数:解密 C++ 回调函数的全部姿势

本篇博客全面解析了 C++ 中回调函数的实现机制与应用场景,从基础的函数指针到现代 C++ 的 `std::function`、lambda 表达式与模板回调,逐步剖析各种实现方式的原理、优劣与使用技巧。同时结合工程实践,探讨了回调函数在异步事件、GUI、插件系统等中的应用,并从性能、调试、现代语言特性等角度提供最佳实践指南。文章旨在帮助读者系统掌握回调编程思维,提升代码解耦性与扩展性。

Lenyiin 3818

什么是c语言指针函数,漫谈C指针:函数名其实也是指针

一般的函数调用一个通常的函数调用的例子:/* 自行包含头文件 */void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */int main(int argc, char* argv[]){MyFun(10); /* 这里是调用MyFun(10) 函数 */return(0);}void MyFun(int x) /* 这里定义一个MyFun函数 */{p...

weixin_42347731的博客 209

c语言漫函数,漫谈C指针:函数名其实也是指针

一般的函数调用一个通常的函数调用的例子:/* 自行包含头文件 */void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */int main(int argc, char* argv[]){MyFun(10); /* 这里是调用MyFun(10) 函数 */return(0);}void MyFun(int x) /* 这里定义一个MyFun函数 */{p...

weixin_35112917的博客 335

【漫谈C语言和嵌入式063】C语言中的指针及其意义

指针是C语言中最核心的概念之一,它使得C语言能够直接操作内存、实现动态内存分配、优化性能,并实现复杂的数据结构和函数操作。虽然指针可能难以掌握,但它赋予了C语言极大的灵活性和控制力。

2403_83044722的博客 983

漫谈Wine之一: WINE的系统结构

我们所要开发的Linux兼容内核主要的一个源泉就是Wine。另一方面,我们之所以要开发兼容内核的的重要原因之一,就是因为Wine不能很好地解决在Linux内核上运行Windows应用的问题。为此,我们应该对Wine进行比较深入的研究,取得对Wine的深入理解,特别是要搞清两个问题:1)Wine是什么样的?2)为什么Wine是那样的?如此才能明白我们为什么要开发兼容内核,以及我们将怎样来开发兼容内核

smqjzzm1988的专栏 2992

漫谈C指针第十七讲---定义函数的指针类型

就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来声明函数指针变量。我先给你一个自定义数据类型的例子。#include "stdio.h"typedef int* PINT; /* 为int* 类型定义了一个PINT的别名*/ int main() { int x; PINT px = &x; /* 与“int *px=&x;”是等价的。PINT类型其实就是

爱橙子的OK绷的专栏 367
上一篇: {译}函数指针漫谈(1)
下一篇: {译}函数指针漫谈(3)
luckheadline
博客等级 码龄21年 7粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值