簡體   English   中英

我應該如何理解這個迭代函數

[英]How should I understand this iteration function

我正在努力將C FIFO隊列實現移植到我的代碼中,並且我不喜歡包含我不理解的功能。 此功能有什么作用? 我看到它返回一個整數值,但我不知道這意味着什么。 什么是(*iter)參數? 我沒有在頭文件或實現文件中看到此類型的聲明。

您可以在此處找到標題
您可以在此處找到實現

有問題的函數復制如下:

int fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
{
    fifonode_t *fn;
    int rc;
    int ret = 0;

    for (fn = f->f_head; fn; fn = fn->fn_next) {
        if ((rc = iter(fn->fn_data, arg)) < 0)
            return (-1);
        ret += rc;
    }

    return (ret);
}

int (*iter)(void *data, void *arg)是一個函數指針 調用fifo_iter ,您在第二個參數中傳遞了一個回調函數。 該函數必須具有如下簽名:

int my_callback(void* data, void* arg)

然后, fifo_t每個項目調用此函數。 它將在data參數中傳遞fn_data成員。 無論您為arg傳遞給fifo_iter什么, fifo_iter將作為其arg參數傳遞給iter 這是僅將通用“上下文”信息傳遞給回調的常見方法,而不必訴諸難看的,線程不安全的全局變量。

因此,您可以像這樣使用它:

int my_callback(void* data, void* arg) {
    printf("my_callback(%p, %p)\n", data, arg);
    return 0;    // always continue
}

void test(void) {
    fifo_t myfifo;    // Needs initialized and populated...

    fifo_iter(&myfifo, my_callback, NULL);
}

此外,我們看到它以特殊方式使用iter的返回值。 首先,如果iter返回負值,則迭代立即停止, fifo_iter返回-1。 這可能是“早期失敗”。 否則,它將(正)返回值累加到ret ,然后返回該值。

擴展我的示例。 假定fifo fn_data成員指向字符串。 這將計算FIFO中所有字符串中的大寫和小寫字母的總數,並返回所有字符串的總長度。

// The context that we'll maintain during the iteration
struct my_context {
    int caps;
    int lowers;
};

// The callback function, called for every string in the FIFO.
int my_callback(void* data, void* arg) {
    const char* str = data;            // Node data is a string
    struct my_context *ctx = arg;      // Arg is my context

    // If any string in the FIFO has a !, abort immediately.
    if (strchr(str, '!'))
       return -1;

    // Update the context to include the counts for this string
    ctx->caps   += count_capital_letters(str);
    ctx->lowers += count_lowercase_letters(str);

    // fifo_iter will accumulate this length
    return strlen(str);
}

// Test driver function
void test(void) {
    fifo_t myfifo;
    struct my_context ctx;
    int total;

    // Assuming these functions exist:
    fifo_init(&myfifo);
    fifo_append(&myfifo, "Stack");
    fifo_append(&myfifo, "Overflow");

    // Initialize the context
    ctx.caps = 0;
    ctx.lowers = 0;

    // Iterate over myfifo, passing it a pointer to the context
    total = fifo_iter(&myfifo, my_callback, &ctx);

    if (total < 0) {
        // Any string had a '!'
        printf("Iteration failed!\n");
        return;
    }

    printf("total=%d caps=%d lowers=%d \n", total, ctx.caps, ctx.lowers);
}

如果您仔細研究Linux內核源代碼,那么到處都會看到這種結構。

對於像我們這里這樣的簡單FIFO,似乎不值得。 但是,當您處理更復雜的數據結構(例如哈希列表和RCU列表)時,將迭代邏輯僅保留在一個位置並利用回調以所需的任何方式處理數據更為有意義。

它遍歷該結構,在每個元素上調用參數函數iter() 如果元素返回負數,則迭代停止並返回-1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM