1. 程式人生 > >研發之路: C程式碼註釋引發的“血案”

研發之路: C程式碼註釋引發的“血案”

出處:研發之路: C程式碼註釋引發的“血案”

沒有血案,但有些衝突。不是程式碼bug,我要講註釋風格。

這位看官,既然來了,且讀且評吧。故事是真實的,如有雷同純屬巧合。

  事情是這樣的,有人離職,公司調我補缺。那個系統一直有個工程師在維護,參與該系統的新人來了又走,他始終泰若磐石。剛過去一個禮拜,我就心下竊吼:“坑爹啊!”,也徹底體會到什麼叫---絕對的權威、專家。該軟體系統,是公司發家的支柱產品,涉及十幾個國家x七八個機型,700+個檔案(C語言,所有.c .h檔),十幾萬行程式碼,盡兩百個跨模組全域性變數,編譯條件成百上千......(好吧,這是找藉口、吐槽的節奏)

  儘管有名義上的交接,和幾次和聲細語的密切指導。但真正獨立展開工作時,許多小功能增刪改,我都要折騰個好幾天才能釐清程式碼呼叫關係、演算法原理,然後找到修改點謹慎細微龜速前行。進度追蹤的人有的時候也催毛了,直接請專家大師出手,咔咔咔,不到半天就搞定了。當然,前期我當然儘量的”不恥上問”,但人嗎,總是有遇到被激發“骨氣”的時候。

  這幾天,好不容易搞好一個全新的功能模組,把程式碼推送給他合併編譯。不曾想,出現了讓我泣血的一幕。

  我眼睜睜地、眼睜睜看著她把我辛苦敲入的程式碼註釋/**/通通換成//,一份精美的程式碼,頓時成渣。

  我詢問緣由,她的回答是: 當代碼裡面充滿註釋符號/**/時,她想要用/**/註釋整段程式碼時,就會很麻煩。 我理解了,因為/**/不支援巢狀。比如下面這樣的語句是編譯不過的。

  /*

  a = b+c; /* 註釋 */

  */

  我的手擡了擡,終究作罷。雖然我感覺到尊嚴被踐踏,心愛的作品被蹂躪,但我還是開始反思。

  許多軟體規範、專家、有經驗的工程,都建議或要求註釋程式碼最好使用 /**/,他們的理由大略如下:

  1. “//” 的註釋的嚴密性不夠。 例如

  // 註釋語句 ??/

  a = b+c;

  此時,a = b+c在一些編譯器不會被執行。

  因為'??/'會被編譯器當作 \,變成C語言的換行符。於是這段程式碼等同於

  // 註釋語句 a = b+c ;

  就會被註釋掉。大家有興趣的,不妨去搜索一下'C語言 三字母詞'

  當然,哪怕沒有??/, 自己打盹碰到delete鍵也是會遮蔽掉a=b+c的

  2. “//” 的註釋,是C++發展後才引進的。 有些早期的C編譯器對這種註釋是不支援的。程式碼要做到全平臺相容,這點是必需要考慮的。

  因此,老外定義的C語言軟體規範,無論是MISRA還是CMMI,一般都要求所有程式碼註釋必須使用/**/。

  君不見,那uCOS的最新版本原始碼,所有註釋都是/**/。

  君不見,那STM32的最新韌體庫,洋洋灑灑幾十個檔案,通篇皆沒有用到//。

 

  正是基於這樣的理由,讓我的心中充滿了慍怒。但我仍然沒有當場反駁她,因為這些理由還有些蒼白無力。

  1. 當時,那個什麼三字母詞“??x”到底是什麼我已經忘了,沒法立刻做試驗編譯給她看。

  而且時候我裡面作了編譯實驗,得到的是

  'filename.c', line xxxx: Warning: #2532-D: support for trigraphs is disabled xx程式碼語句xx // ??/

  trigraph金山詞霸---> [traigra:f]三字母詞

  看吧,編譯器都警告了,預設是不支援的。

  2. 而且,所謂的//是C++的,早期的c編譯器不支援。

  這點誰鳥啊,我們只要現在,只用最新版本的編譯器。

  所以,我還要繼續思考。

  我要維護這個傳統,為自己代言......

我開始思考,還有什麼強勁有力的理由,來支援我恪守的真理:c語言程式碼註釋必須使用/**/.

  有的!

  倘若所有程式碼裡面的註釋用到/**/時,當你要註釋掉這段程式碼時,如果不想忍受編譯器的巢狀報警,又懶得把一個個/**/換成//的話。那麼你還有如下選擇。

  1) 慎重思考下是否刪光這段程式碼,如果還有些不捨,那就先'備份'(git推送)一下再刪光。因此,

  理由一:使用/**/註釋程式碼,會使軟體系統減少冗餘的殭屍程式碼,鼓勵程式設計師的程式備份行為。

  2) 或者用編譯條件圈起來,如下。

  #if (XXX_ENABLE)

  func(a, b, c); /* 註釋 */

  ...... /* 註釋 */

  #endif

  那麼你不得不考慮xxx的命名,如何更加一目瞭然,再寫點註釋什麼的,表明對這段程式碼“棄而不捨”的緣由。因此,

  理由二:使用/**/註釋程式碼,會鼓勵程式設計師刪除程式碼時,三思而後行,並且註明捨棄的理由。

  3) 當然,偷懶的人還是會用 #if 0 #endif圈起來, 如下,

  #if 0

  func(a, b, c); /* 註釋 */

  ...... /* 註釋 */

  #endif

  而且不會寫任何註釋表明刪除的理由。然而,“#if 0”是一個如此的醒目,很容易成為一個評估軟體質量、工作績效的搜尋關鍵詞。從管理的角度,這個是可以量化的。因此,

  理由三: 使用/**/註釋程式碼,有利於公司進行軟體質量控管,對程式設計師績效考核。

  這三個理由,足夠為自己代言嗎?

延伸閱讀:
 

C語言實現FFT(快速傅立葉變換)
C語言的那些小祕密之動態陣列
C語言的那些小祕密之異常處理
硬體工程師的10個C語言技巧
C語言難點及分析
如何寫出高效優美的微控制器C語言程式碼?

回覆:運算放大器、傅立葉、阻抗、小波、type c、訊號、微控制器、示波器、模擬、畢設、電阻、DSP、電路、面試、電源、FPGA、USB、CAN(回覆你想看的)