river
river

Reputation: 734

Ask for explanation of a kernel macro: hlist_nulls_for_each_entry

I am confused with a Linux kernel function definition. hlist_nulls_for_each_entry is defined as a for loop, and it's easy to understand the most info。

#define hlist_nulls_for_each_entry(tpos, pos, head, member)            \
    for (pos = (head)->first;                          \
         (!is_a_nulls(pos)) &&                         \
        ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

While I can't understand the following sentence, why do the author add ; 1; to the end. Why not move the sentence tpos = hlist_nulls_entry(pos, typeof(*tpos), member) to following of pos = pos->next .

 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1;});

Upvotes: 1

Views: 129

Answers (1)

user2736738
user2736738

Reputation: 30926

This is a compound statement. Last 1 is there so that the value of the statement block evaluates to 1 making the condition true.

From the documentation

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct.

Here irrespective of what turns out to be the assigned value of tpos we want to execute the for loop. That's why there is 1; there. The loop will stop on the other condition specified, which is (!is_a_nulls(pos)).

Yes you can move it to with the incremement operation also -separated by commma operator. We can format the loop to do that also. But remember that here we are running the loop for initial value also, so we need to work with it before incrememnt is done.

Note that - this is a gcc extension. C standard doesn't offer this. This means it is not a portable solution. If you write it in same old for loop block you will be good to go based on portability.

Upvotes: 3

Related Questions