1. 程式人生 > >如何理解typedef void (*pfun)(void)

如何理解typedef void (*pfun)(void)

原文地址:https://www.cnblogs.com/guanguangreat/p/6117988.html

問題:

      在剛接觸typedef void (*pfun)(void) 這個結構的時候,存在疑惑,為什麼typedef後只有一“塊”東西,而不是兩“塊”東西呢?那是誰“替代”了誰啊?我總結了一下,一方面是對typedef的概念不清晰,另一方面受了#define的影響,犯了定向思維的錯誤。

概念理解:

typedef 只對已有的型別進行別名定義,不產生新的型別;

#define 只是在預處理過程對程式碼進行簡單的替換。

清晰瞭解兩個概念後,發現它們就是兩個不同的概念,並沒有太多的聯絡。

類比理解:

typedef  unsigned int  UINT32;  // UINT32 型別是unsigned int

UINT32 sum;                                 // 定義一個變數:int sum;

typedef  int  arr[3];                     // arr 型別是 int[3];(存放int型資料的陣列)

arr a;                                              // 定義一個數組:int a[3];

同理:

typedef  void (*pfun)(void);         // pfun 型別是 void(*)(void)

pfun main;                                       // 定義一個函式:void (*main)(void);

在部落格上看到一個經典的函式指標用例:

為保護原創作者的權益,以下例子程式碼不作修改:

#include<stdio.h>

typedef int (*FP_CALC)(int, int);

//注意這裡不是函式宣告而是函式定義,它是一個地址,你可以直接輸出add看看

int add(int a, int b)

{

      return a + b;

}

int sub(int a, int b)

{

      return a - b;

}

int mul(int a, int b)

{

      return a * b;

}

int div(int a, int b)

{

      return b? a/b : -1;

}

//定義一個函式,引數為op,返回一個指標。該指標型別為 擁有兩個int引數、

//返回型別為int 的函式指標。它的作用是根據操作符返回相應函式的地址

FP_CALC calc_func(char op)

{

      switch (op)

      {

           case '+' : return add;   // 返回函式的地址

           case '-' : return sub;

           case '*' : return mul;

           case '/' : return div;

           default:

                 return NULL;

      }

      return NULL;

}

//s_calc_func為函式,它的引數是 op,返回值為一個擁有兩個int引數、返回型別為int 的函式指標

int (*s_calc_func(char op)) (int, int)

{

      return calc_func(op);

}

//終端使用者直接呼叫的函式,該函式接收兩個int整數,和一個算術運算子,返回兩數的運算結果

int calc(int a, int b, char op)

{

      FP_CALC fp = calc_func(op);                  // 根據預算符得到各種運算的函式的地址

      int (*s_fp)(int, int) = s_calc_func(op);  // 用於測試

      // ASSERT(fp == s_fp);                          // 可以斷言這倆是相等的

      if (fp)

return fp(a, b);  //根據上一步得到的函式的地址呼叫相應函式,並返回結果

      else

return -1;

}

void main()

{

      int a = 100, b = 20;

      printf("calc(%d, %d, %c) = %d\n", a, b, '+', calc(a, b, '+'));

      printf("calc(%d, %d, %c) = %d\n", a, b, '-', calc(a, b, '-'));

      printf("calc(%d, %d, %c) = %d\n", a, b, '*', calc(a, b, '*'));

      printf("calc(%d, %d, %c) = %d\n", a, b, '/', calc(a, b, '/'));

}

結合程式碼理解:

程式碼作者在註釋中表述得很清楚,個人覺得最有意思就是一下這個函式:

FP_CALC calc_func(char op)    <-->   int (*calc_func(char op)) (int, int)

  程式碼作者試圖在斷言中說明這個關係,相比較,還是FP_CALC calc_func(char op)函式更能表達編碼者的意圖:calc_func函式返回FP_CALC型別的指標,是一個函式指標,這個函式的形式是int (函式名)(int, int),程式碼中int add(int a, int b)、int sub(int a, int b)…正是這樣的格式。

(修改於 2016-12-22  19:23:37)

在閱讀《C和指標》的時候,我猛然想起還有一個東西叫“函式指標陣列”,也就是書中所描述的新概念:轉移表。

下面是實現一個簡易計算器的核心程式碼:

複製程式碼
 1 switch(oper){
 2   case ADD:
 3     result = add(oper1, oper2);
 4     break;
 5 
 6   case SUB:
 7     result = sub(oper1, oper2);
 8     break;
 9 
10   case MUL:
11     result = mul(oper1, oper2);
12     break;
13 
14   case DIV:
15     result = div(oper1, oper2);
16     break;
17   ……
18 }
複製程式碼

這是一種我們常用的實現方式,在書中提到有一個最起碼看起來更高階,更簡潔的方法:

複製程式碼
1 double add(double, double);
2 double sub(double, double);
3 double mul(double, double);
4 double div(double, double);
5 ……
6 Double (*oper_fun[])(double, double) = {add, sub,mul,div,…};
7 呼叫時:
8 result = oper_func[oper](oper1, oper2);
複製程式碼

為什麼要呼叫函式來執行這些操作呢?把具體操作和選擇操作的程式碼分開是一種良好的設計方案。

——《C和指標》

相關推薦

函式指標-如何理解typedef void (*pfun)(void)

問題: 在剛接觸typedef void (*pfun)(void) 這個結構的時候,存在疑惑,為什麼typedef後只有一“塊”東西,而不是兩“塊”東西呢?那是誰“替代”了誰啊?我總結了一下,一方面是對typedef的概念不清晰,另一方面受了#define的影響,犯了定向思維的錯誤。

如何理解typedef void (*pfun)(void)

原文地址:https://www.cnblogs.com/guanguangreat/p/6117988.html問題:      在剛接觸typedef void (*pfun)(void) 這個結構的時候,存在疑惑,為什麼typedef後只有一“塊”東西,而不是兩“塊”東

關於typedef int (init_fnc_t) (void);理解

來源:http://blog.chinaunix.net/uid-22979746-id-2590215.html 位於lib_arm/board.c typedef int (init_fnc_t) (void);    //自定義新的資料型別init_

typedef void (*Fun) (void) 的理解——函式指標——typedef函式指標

首先介紹大家比較熟悉的typedef int i;//定義一個整型變數i typedef int myInt; myInt j;//定義一個整型變數j 上面介紹得是我們常用的比較簡單的typedef的用法,下面首先介紹一下函式指標。 函式指標的形式: 形式1:返回

typedef void (*pFunction)(void);講解的特別好,適合新手學習

剛在網上看到的,講解的特別好,適合新手學習,高手請忽略...轉自:http://blog.csdn.net/zyboy2000/article/details/4202349(*(void(*)())0) ()  等同 ((void(*)())0) ()    ----原因

typedef知識點 和 void* test(void*)這個函式作為引數的知識點

typedef  void(*fun)(void); void test(void) { std::cout << "111"; }  int main() { fun f = &test; (*f)(); return 0; } //第一個是typed

每日程式設計訓練20150909:typedef void (* unitest_func_t) (void);

#include <stdio.h> #include <string.h> typedef void (* unitest_func_t) (void); typedef

C++ Primer 學習筆記與思考_7 voidvoid*指針的使用方法

能夠 amp space turn begin member use mem urn (一)void的含義 void的字面意思是“無類型”,void差點兒僅僅有“凝視”和限制程序的作用,由於從來沒有人會定義一個void變量,讓我們試著來定義: void a;

void(*p)(void)和void(*p())(void)的區別

scw www spa blank www. rec left href mgo 0頌姿Y3榮qCK釉籃http://huiyi.docin.com/zgy332 I44盎7WMC17司O械狡http://huiyi.docin.com/lpsii596 9Lv昭賭95

voidvoid*的用法

1、void的作用   c語言中,void為“不確定型別”,不可以用void來宣告變數。如:void a = 10;如果出現這樣語句編譯器會報錯:variable or field ‘a’ declared void。   在C語言中void 常常用於:對函式返回型別的限定和對函式引數限

[轉]C/C++:學習voidvoid*詳解

void與void*詳解 void 無型別    void* 無型別指標 可以指向任意型別的資料。 void: 1.函式沒有返回值,宣告為void型別 2.函式無引數。 3.函式的引數可以是任意型別的指標  void*。 【void真正發揮的作用在於】: 1)

Java中 java.lang.Voidvoid 有什麼作用和區別

答:void關鍵字表示函式沒有返回結果,是java中的一個關鍵字。java.lang.Void是一種型別,例如給Void引用賦值null的程式碼為Void nil=null; 。   通過Void類的原始碼可以看到,Void型別不可以繼承與例項化。      final 

Void & void Void用在泛型

public Void setStr(String key,String value)throws Exception{ RetryTemplate retryTemplate=initRetryTemplate(); retryTemplate.execute(new RetryCallba

關於void*與void**的區別

由於void就是不檢查資料型別,所以,對於編譯器來說, void* 和 void** ,甚至後面n個 * ,都是一樣的. 問題的關鍵在於,讓我們這些程式設計的人可以區分. 原則上,void* 可以是一個一級指標,二級指標,甚至是n級指標. 但我們的使用習慣是, 一個 * 代表

關於keil卡在systeminit中,然後出現void HardFault_Handler(void)的幾個問題詳解

版權宣告:本文為博主原創文章,未經博主允許不得轉載。    https://blog.csdn.net/u013184273/article/details/83860802 相信很多程式設計師在用keil的時候都會遇到在模擬除錯時,一直停在SystemInit()中的等待晶

java.lang.Voidvoid的比較及使用

void關鍵字表示函式沒有返回結果,是java中的一個關鍵字。 java.lang.Void是一種型別。例如給Void引用賦值null。 Void nil = null; 通過Void類的程式碼可以看到,Void型別不可以繼承與例項化。 public final cl

void type && void pointer(void *,pointer to void type) && Null pointer

void type void pointer(void *,pointer to void type) 1 ANSI C和C ++支援void指標或void *作為通用指標型別。 指向void的指標可

【Linux開發技術之常見問題】一個建立執行緒時常見的問題:invalid conversion from `void*' to `void*(*)(void*)

void main_thread ( void *ptr ) {   char *message1 = "Thread 1";   char *message2 = "Thread 2";   pthread_t thread3, thread4;   int iret3, iret4;  

C/C++中的voidvoid*

一、void void關鍵字表示“空型別”的概念。但是,這裡的“空型別”不表示“任意型別”,而是表示不存在的意思,也就是說C/C++不允許你寫語句void a,不存在型別為void的東西. void表示“不存在”的意思,可以從void的兩個應用中加以體現: 1、void作為

voidvoid*的用法總結和注意點

void的字面意思是空型別,void *的意思是空型別指標,void 不是一個真正的型別,我們在宣告變數的時候從來不會像下面這樣宣告: void a; 如果我們寫了一行這樣的程式碼,某些編譯器會直接報錯,有些則不會,但也沒有任何意義。 void真正的用途在下面兩個