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

GCC 巢狀函數擴展:C 語言中的閉包與詞法作用域

     編輯:關於C語言

前言

巢狀函數 是 GCC 擴展,非標準 C。它帶來閉包與詞法作用域特性,讓 C 具備函數式語言風格能力。

基本語法

double foo(double a, double b) {
    double square(double z) { return z * z; }  // 巢狀函數
    return square(a) + square(b);
}

進階特性

1. 詞法作用域:捕獲外層變數

void bar(int *array, int offset, int size) {
    int access(int *array, int index) {
        return array[index + offset];  // 捕獲 offset
    }
    for (int i = 0; i < size; ++i) {
        // 使用 access(array, i)
    }
}

2. 標籤跳轉:非本地 goto

void bar(int *array, int offset, int size) {
    __label__ failure;
    int access(int *array, int index) {
        if (index > size) goto failure;  // 跳轉至外層標籤
        return array[index + offset];
    }
    for (int i = 0; i < size; ++i) { /* ... */ }
    return 0;
failure:
    return -1;
}

3. 函數指標回呼:向上傳遞

int (*get_square(void))(double) {
    double square(double z) { return z * z; }
    return square;  // 回傳巢狀函數位址
}
// 呼叫端:int (*f)(double) = get_square(); f(3.0);

警告:外層函數返回後,其堆疊框架失效,呼叫此函數指標屬未定義行為(GCC 透過 trampoline 於堆疊生成代碼支援,但極度危險)。

實現原理:Trampoline

  • GCC 在呼叫者堆疊動態生成一小段機器碼
  • 該碼片載入靜態鏈結指標,跳轉至巢狀函數實體
  • 需堆疊可執行權限(-z execstack 或 mprotect)
  • 安全風險:堆疊執行易遭緩衝區溢位攻擊利用

可移植替代方案

需求標準 C 方案C++ 方案
狀態捕獲結構體 + 函數指標Lambda 表達式
回呼void* context + 函數指標std::function + Lambda
閉包手動實現環境結構體Lambda 自動捕獲

結語

巢狀函數展示編譯器擴展的強大與風險。生產代碼建議使用標準 C/C++ 替代方案,確保可移植性與安全性。

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