你是否被要求寫的代碼需要0 erros, 0 warnings? 或者你的項目是否需要做靜態(tài)代碼檢測?0 erros是一定要做到,而0 wanring有時候會讓你抓狂。前面轉了一篇數(shù)組內包含頭文件的寫法,看起來對此類不太常見的寫法大家比較感興趣,今天來分享一個去除函數(shù)參數(shù)未使用warning的技巧。使用void即可輕松去除,如果你知道怎么用,可以關閉此文了,因為很簡單。沒用過的則可以學習學習。
先舉個栗子
看一個都熟悉經典栗子:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello World\n");
return 0;
}
這程序簡單吧?不能再簡單了!編譯運行正常,看到了Hello World,編譯也沒有錯:
But,卻有兩個warning! 嗯?這樣一個沙雕代碼,管它是否warning!沒錯,這里確實可以不去管??墒侨绻阕鲆恍┨厥庑袠I(yè)的嵌入式開發(fā),比如汽車、醫(yī)療、工控、軍工等,其代碼都可能要求做靜態(tài)代碼檢測,如果你函數(shù)中的參數(shù)沒被使用,就一定會拋出這樣的警告!要求嚴格的企業(yè),這樣的代碼是不可以提交的,比如工業(yè)做IEC61508功能安全認證,代碼是需要提交給認證機構審查的,這樣帶warning的,你還想拿證嗎?同樣在醫(yī)療、汽車領域,則要求就更為嚴謹了,就更遑論軍工了。
那么怎么整呢?
且看lwip的做法
在\src\include\lwip\Arch.h中定義了這樣一個宏:
#ifndef LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x) (void)x
#endif /* LWIP_UNUSED_ARG */
讓我們來隨便搜一個使用的地方:
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
{
#if LWIP_TCP
struct api_msg msg;
err_t err;
/* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
LWIP_UNUSED_ARG(backlog);
LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
msg.function = do_listen;
msg.msg.conn = conn;
#if TCP_LISTEN_BACKLOG
msg.msg.msg.lb.backlog = backlog;
#endif /* TCP_LISTEN_BACKLOG */
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
#else /* LWIP_TCP */
LWIP_UNUSED_ARG(conn);
LWIP_UNUSED_ARG(backlog);
return ERR_ARG;
#endif /* LWIP_TCP */
}
你看,這個函數(shù)里有三處使用這個宏?細心的童鞋可能會說,既然不用函數(shù)參數(shù)原型把它干掉不就好了嗎?這里有兩個原因:
- 其一、有的參數(shù)在開發(fā)中可能是預留接口,項目是不斷迭代開發(fā)的,有些功能可能剛開始沒做,但是接口有可能提前定義好了;
- 其二、函數(shù)內部有可能有不同的編譯分支,有的分支有可能不會完全使用函數(shù)參數(shù)
比如上面的例子,這是一個偵聽的接口函數(shù),BACKLOG 有可能會被裁剪掉,此時如果沒有前面的LWIP_UNUSED_ARG(backlog);,就會報backlog參數(shù)未使用的警告,如果是LWIP_TCP使能,則conn 及backlog又會報警告。
或許你會說,這有什么關系,應該也不影響使用,是的,姑且不考慮代碼是否需要嚴格的審查。想lwip這樣一個開源庫里,類似的地方有很多很多,如果沒有這樣的處理,使用者一編譯,哎呀,媽呀! 一堆一堆的warning! 這個開源庫使用者的使用體驗還會好么?如果你的應用如果沒有編譯錯誤還好,但凡有那么一個錯誤,就需要在很多warning中就找那一個error! 體驗酸爽否?
這啥原理呢?
(void) x 不會對代碼做任何額外的操作,僅僅以此來告訴編譯器不要報unused警告出來!至于是否所有編譯器是否都支持這么干,
這其實是編譯器對于unused類型的處置方式,不同的處置方式,比如:
- IAR中,如果你不做上述處置,你還可以這樣壓掉unused警告:
#pragma diag_suppress=Pe550
- 又譬如,在GCC/Clang中,也可以這么干:
int fun (__attribute__((unused)) int a)
{
return 0;
}
也或者加上-Wno-unused-parameter 編譯選項。
.....
不同的編譯器處置方式會略有差異,如果遇到了,知道這么回事,去查查看就知道了。如果你還需要做靜態(tài)代碼檢查,根據(jù)你使用的工具去查查文檔也會很快掌握,工具本身的方法,個人覺得在代碼中去實現(xiàn)會更好一些。
回到Hellworld
現(xiàn)在讓我們來試試void在Helloworld中的使用,加上void試試:
#include <stdio.h>
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
printf("Hello word\n");
return 0;
}
好了,今天的分享結束了,你get到這個小技巧了嗎?