首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言複雜函數指針聲明解讀:void (*signal(int, void(*)(int)))(int) 逐層拆解

     編輯:關於C語言

目標聲明

void (*signal(int signo, void (*func)(int)))(int);

這是標準庫 `` 中 `signal` 函數的原型。乍看極其複雜,實則遵循「從內向外、從右向左」的聲明解讀規則。

逐層拆解步驟

第 1 層:最內層參數 `void (*func)(int)`

  • `func` 是一個函數指針
  • 指向的函數:參數 `int`,返回 `void`
  • 等價 `typedef void (*Handler)(int);`

第 2 層:`signal` 的參數列表

int signo, void (*func)(int)
// 即:int signo, Handler func
  • `signal` 接受兩個參數:信號編號 `signo`、處理函數指針 `func`

第 3 層:`signal` 本身是函數指針

void (*signal(...))(int)
// 讀法:signal(...) 返回一個指針,該指針指向「參數 int、返回 void」的函數

第 4 層:整體語義

signal 是一個函數(非指針),其:

  • 參數:`int signo`、 `void (*func)(int)`
  • 返回值:`void (*)(int)` —— 即舊的信號處理函數指針

等價 typedef 重寫(強烈推薦)

// 1. 定義信號處理函數類型
typedef void (*sig_handler_t)(int);

// 2. signal 原型變得清晰可讀
sig_handler_t signal(int signo, sig_handler_t func);

實際調用示例

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

void my_handler(int sig) {
    printf("捕獲信號 %d\n", sig);
}

int main() {
    // 註冊 SIGINT (Ctrl+C) 處理函數,保存舊處理函數
    void (*old_handler)(int) = signal(SIGINT, my_handler);
    
    printf("按 Ctrl+C 測試...\n");
    while (1) sleep(1);
    
    // 恢復舊處理函數(示意)
    // signal(SIGINT, old_handler);
    return 0;
}

聲明解讀通用口訣(右左法則 / Clockwise Spiral Rule)

  1. 從標識符(此處 `signal`)開始
  2. 向右找 `()` 或 `[]` → 函數/數組
  3. 向左找 `*` → 指針
  4. 繼續向右再向左,螺旋式展開
  5. 遇到類型關鍵字(`int` `void` 等)停止

應用於 `void (*signal(int, void(*)(int)))(int)`:

signal                     // 標識符
signal(           )        // 是函數,參數見括號內
signal(int, void(*)(int))  // 參數:int 和 函數指針
(*signal(...))             // 返回指針
void (*signal(...))(int)   // 指向「參數 int、返回 void」的函數

同類複雜聲明練習

| 原聲明 | 含義 | typedef 簡化 | |--------|------|--------------| | `int *(*foo)(double)` | `foo` 是函數指針,參數 `double`,返回 `int*` | `typedef int* (*FooPtr)(double);` | | `void (*arr[10])(int)` | `arr` 是大小 10 的數組,元素為函數指針 | `typedef void (*Handler)(int); Handler arr[10];` | | `float *(*(*bar())[5])()` | `bar` 是函數,返回指向「5 元素數組」的指針,數組元素是函數指針,返回 `float*` | 分層 typedef... |

工程建議

  1. 永遠使用 typedef 將複雜函數指針類型命名,API 文檔可讀性提升 10 倍
  2. 避免在參數列表直接寫函數指針聲明,改用類型別名
  3. 編譯器報錯時,用 `cdecl` 工具(Linux 自帶或在線版)驗證聲明含義

總結

`signal` 聲明雖長相嚇人,但結構清晰:函數接受信號號和處理器,返回舊處理器。掌握「從標識符螺旋展開」解讀法 + `typedef` 封裝,即可輕鬆應對所有複雜函數指針聲明。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved