簡體   English   中英

為什么這些C宏不寫為函數?

[英]Why are these C macros not written as functions?

我正在研究netstat工具(Linux)的代碼,AFAIK大多會讀取該文件/proc/net/tcp文件並從中漂亮地打印出來。 (我現在的焦點是-t模式。)

我為作者選擇的編碼風格感到困惑:

static int tcp_info(void)
{
    INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)", tcp_do_one);
}

哪里

#define INFO_GUTS6(file,file6,name,proc)                \
 char buffer[8192];                                     \
 int rc = 0;                                            \
 int lnr = 0;                                           \
 if (!flag_arg || flag_inet) {                          \
    INFO_GUTS1(file,name,proc)                          \
 }                                                      \
 if (!flag_arg || flag_inet6) {                         \
    INFO_GUTS2(file6,proc)                              \
 }                                                      \
 INFO_GUTS3

哪里

 #define INFO_GUTS3                                      \
  return rc;

#if HAVE_AFINET6
#define INFO_GUTS2(file,proc)                           \
   lnr = 0;                                              \
   procinfo = fopen((file), "r");                        \
   if (procinfo != NULL) {                               \
     do {                                                \
       if (fgets(buffer, sizeof(buffer), procinfo))      \
          (proc)(lnr++, buffer);                          \
     } while (!feof(procinfo));                          \
     fclose(procinfo);                                   \
   }
#else
#define INFO_GUTS2(file,proc)
#endif

等等

顯然,我的編碼感覺是傾斜的,並說“那些應該是功能”。 我認為這些宏不會帶來任何好處。 它會破壞可讀性,等等。

周圍的人是否熟悉此代碼,是否可以弄清楚這里的“ INFO_GUTS”是什么,以及是否有(或仍然有)這種奇怪的編碼風格的原因?

如果您對它們的使用感到好奇,則完整的依賴圖如下所示:

#               /--->   INFO_GUTS1  <---\    
#  INFO_GUTS --*        INFO_GUTS2  <----*---- INFO_GUTS6
#      î        \--->   INFO_GUTS3  <---/           î 
#      |                                            |
# unix_info()              igmp_info(), tcp_info(), udp_info(), raw_info()

您認為“那些宏應該是函數”對我來說似乎是正確的。 我希望將它們視為函數。

知道使用宏的頻率將很有趣。 但是,使用的次數越多,如果它們是實函數而不是宏,則應該節省更多空間。 宏非常大,並且本身會使用(本來就很慢)I / O函數,因此使用宏不會加快速度。

現在,如果要內聯替換函數,則可以在C(以及C ++)中使用inline函數。


您也可以認為INFO_GUTS2應該使用簡單的while循環,而不是do ... while循環; 如果滿足以下條件,則只需檢查一次EOF:

while (fgets(buffer, sizeof(buffer), procinfo))
    (*proc)(lnr++, buffer);

照原樣,如果通道上存在錯誤(而不是EOF),則代碼可能會陷入無限循環。 fgets()將失敗,但feof()將返回false(因為尚未到達EOF;它遇到了錯誤-請參閱ferror() ),因此循環將繼續。 這不是一個特別合理的問題; 如果文件打開,您幾乎不會出錯。 但是可能是個問題。

沒有理由。 一般而言,編寫代碼的人可能對代碼優化非常困惑,尤其是內聯的概念。 由於編譯器很可能是GCC,因此有多種方法可以實現函數內聯,即使對該函數甚至必須進行內聯,我也非常懷疑。

內聯包含文件I / O調用的函數與刮削大象以減輕其重量是一樣的...

實施可選的IPv6支持是一個可怕的主意。 您必須瀏覽歷史記錄以進行確認,但是存檔似乎只能恢復到1.46,隱含的損壞為1.20+。

我發現一個git存檔可以追溯到1.24,並且仍然存在。 較舊的代碼令人懷疑。

BusyBox或BSD代碼均不包含此類混亂代碼。 因此它出現在Linux版本中,並且遭受了嚴重破壞。

宏生成代碼:調用宏時,整個宏定義將在調用位置擴展。 如果說INFO_GUTS6是一個函數,它將無法聲明例如緩沖區變量,該變量隨后可被宏調用后的代碼使用。 您粘貼的示例實際上非常整潔:-)

暫無
暫無

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

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