Warning: left-hand operand of comma expression has no effect!

首先來看看下面這隻 Macro:

#define UTL_LIST_ALL_ELEMENTS_RO(list, node, data) \
______((node) = UTL_LIST_HEAD(list)); \
______(node) != NULL && ((data) = UTL_LIST_DATA(node), 1); \
______((node) = UTL_LIST_NEXTNODE(node) )

很簡單的 Macro,作用是 Link List 的 Traversal,給 For-Loop 使用。
那為甚麼要特別拿出來討論??

重點在 ((data) = UTL_LIST_DATA(node), 1) 中的 ", 1" ,那到底有甚麼作用呢?

寫一個小程式來看看:

#include
#include

int main()
{
@@int a = 0, i = 10, j = 20;
@@printf( "a = %d\n", ( a = ( i, j ) ) );
@@return 0;
}

結果印出來的答案是 a = 20

事實上,在編譯的時候,如果是 gcc -Wall test.c 的話,我們會發現下面的警告:

test.c: In function ‘main’:
test.c:7: warning: left-hand operand of comma expression has no effect

也就是說,在 C 的語法裡面 (a,b,c,...,n) 的語法裡面,事實上就等於是 n,逗號左邊的全部數值是沒有作用的!!

既然沒有作用,那為甚麼 Macro 會出現這樣的寫法??

我們在看看下面的另一個小程式 test2.c

#include
#include

int main()
{
@@int a = 0, i = 10, j = 20;
@@printf( "a = %d\n", ( a = ( i=i+50, j ) ) );
@@printf( "i = %d\n", i );
@@return 0;
}

最後會印出

a = 20
i = 60

所以,即使在
( a = ( i=i+50, j ) )沒有作用,i=i+50但是仍然會被計算!!

再回到一開始討論的 Macro,對 Link List 的設計者而言,只要 node 存在,就必須要取出該 node 的 data,即使 data 是 NULL (這應該是 Macro 的使用者要考慮的部份)!! 如果不使用
((data) = UTL_LIST_DATA(node), 1)的寫法...那當 data 為 NULL 的時候 Loop 就會終止了,為了避免這個狀況,所以才會有以上的寫法。

明白了以後心情豁然開朗...但我實在不喜歡這樣寫 code
:p

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

Linux Virtual Interface: TUN/TAP