Home > OS >  Can you pass a code block to a function in C?
Can you pass a code block to a function in C?

Time:03-08

I was watching a video on the Linux kernel moving to C99 or C11 possibly and the video was looking at an example for why they are going to do this.

I kept seeing a function being called like this:

list_for_each_entry(pos, &head, member) {
  /* this code gets run for each entry? */
}

I've never seen something like this before in C or C . However, as a Ruby programmer this makes sense to me because I'm used to doing something like this:

arr.each do |item|
  # do something with the item
end

arr.each { |item| single_line_of_code_here }

I never knew that C had this ability? I was trying to learn more about this and my guess is this isn't a function but maybe a macro? Can someone explain to me what's happening here?

Edit: Documentation for this function here: https://www.kernel.org/doc/htmldocs/kernel-api/API-list-for-each-entry.html

CodePudding user response:

Apparently, this IS a macro. The soure code this macro is:

/**
 * list_for_each_entry  -   iterate over list of given type
 * @pos:    the type * to use as a loop cursor.
 * @head:   the head for your list.
 * @member: the name of the list_head within the struct.
 */
#define list_for_each_entry(pos, head, member)              \
    for (pos = list_first_entry(head, typeof(*pos), member);    \
         !list_entry_is_head(pos, head, member);            \
         pos = list_next_entry(pos, member))

The source code (which contains other iterators as well): https://elixir.bootlin.com/linux/v5.16.1/source/include/linux/list.h#L629

CodePudding user response:

Without using preprocessor macros you can accomplish something akin to this with function pointers.

typedef void (*fp_t)(int);

void int_array_iter(int *arr, size_t n, fp_t f) {
    for (size_t i = 0; i < n; i  ) {
        f(arr[i]);
    }
}

void print_int(int i) {
    printf("%d\n", i);
}

int main(void) {
    int arr[] = { 1, 2, 3, 4, 5, 6 };

    int_array_iter(arr, 6, print_int);

    return 0;
}
  • Related