user2702853
user2702853

Reputation: 1

Why use macro to call functions

I was studying the Linux wireless subsystem code and noticed this code (in ieee80211_rx_handlers):

It first defines the macro:

 #define CALL_RXH(rxh)                   \
         do {                            \
                 res = rxh(rx);          \
                     if (res != RX_CONTINUE) \
                         goto rxh_next;  \
         } while (0);

Then the macro is used to call a series of functions:

 CALL_RXH(ieee80211_rx_h_check_more_data)

 CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)

 CALL_RXH(ieee80211_rx_h_sta_process)

 CALL_RXH(ieee80211_rx_h_decrypt)

 CALL_RXH(ieee80211_rx_h_defragment)

 CALL_RXH(ieee80211_rx_h_michael_mic_verify)

My question is, why not just call the functions directly like:

ieee80211_rx_h_check_more_data(rx);

ieee80211_rx_h_uapsd_and_pspoll(rx); 

...

Is it just for the sake of outlining the code for easy reading?

Upvotes: 0

Views: 157

Answers (2)

Chris Tsui
Chris Tsui

Reputation: 472

The do {} while(0) Macro could be easily used in condition block.

#define FUNC1()  doing A; dong B;
#define FUNC2()  do { doing A; doing B; } while(0)

We could use FUNC2() in if condition code block like this:

if (true)
    FUNC2();

But FUNC1() could only be used like this:

if (true) {
    FUNC1()
} 

Upvotes: 0

Potatoswatter
Potatoswatter

Reputation: 137820

Each use of the macro expands into the if check and goto, not just a single function call.

The if tests differ only by which function is called to produce the condition. Because the code would otherwise be repetitive, they used a macro to generate the boilerplate.

They could perhaps have interspersed calls res = xyz( rx ); with a macro expanding to the if … goto part, and then the macro would not take any parameter. How much gets encapsulated into the macro is a matter of code factoring style.

Upvotes: 1

Related Questions