作者ric2k1 (Ric)
看板EE_DSnP
標題Re: [轉錄] So, what's wrong with using macros?
時間Thu Oct 22 12:50:35 2009
※ 引述《dryman (dryman)》之銘言:
: 糟糕,我的推文好像得不到共鳴XD
: 留下一句覺得macro也不錯就不說話了好像也不太好
: 以下是我半生不熟的想法,跟大家分享一下,歡迎大家指教:)
歡迎 & 感謝分享!!
: 最初想用macro時單純因為有太多for迴圈,而且裡面有很多都長這樣:
: for( i=_readBufPtr-_readBuf; i< _readBufEnd-_readBuf; i++)
: cout << "\b";
也許增加個 private member function?
雖然題目說最好不要再增加 functions, 那是為了避免同學就直接硬刻,
而沒有照著 TODO 的建議. 不過像是這種情況當然是可以加 functions 的.
不過上面的 code 也許可以改成:
for (char *ptr = _readBufEnd; ptr != _readBufPtr; --ptr)
cout << "\b";
: 不管是array左移右移,輸出空白、backspace,都需要用到類似的for迴圈
: 這樣也沒什麼不好
: 只是當你有ptr到底的,又有整個buffer的,混在一起看真的會讓人覺得有點不好讀
: 最直覺的想法就是寫個macro來讓它好讀一點
Or maybe some member functions like:
printChar(ptr1, ptr2, char); or
printChar(offset, char);
: 因為coding中必須要方便debug,所以我最初設的macro是
: IDX_PTR 還有 IDX_END
: 來替代指標相減(_readBufPtr-_readBuf 之類的)
: 這樣是為了方便我debug,減少寫錯的機會
: 等到程式撰寫完成功能全部都測試完後,我才開始想如何將程式碼變得更精簡
: 我現在知道的方法有兩種啦
: 一種是用while來取代for loop
: 另一種就是自己設計的macro
: macro我使用的只有
: FOR_PTR_TO_END
: FOR_ENTIRE_BUFFER
: 用法是FOR_PTR_TO_END( cout << "\b"; )
: 基本上我覺得我的用法算是走good coding style的模糊地帶XD
: 如果不是替代的程式碼用法很單純,macro真的不是一個好的solution
: 只是在這個題目中array左移右移,印出空白backspace的地方太多了
: 就算寫function也沒辦法全部都罩住
: 反而是macro用起來很貼切XD
: 可是我想這只能算是特例吧?(也許還有更好的寫法?)
STL 的愛用者可能會建議使用像是 for_each() 這樣的 functional object.
不過不一定簡潔就是了.
: ==============================================================
: google有個很棒的c++ coding style guide
: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
: 裡面也是建議不要用macro:
: Be very cautious with macros. Prefer inline functions, enums, and
: const variables to macros.
: Macros mean that the code you see is not the same as the code the
: compiler sees. This can introduce unexpected behavior, especially
: since macros have global scope.
: Luckily, macros are not nearly as necessary in C++ as they are in
: C. Instead of using a macro to inline performance-critical code,
: use an inline function. Instead of using a macro to store a
: constant, use a const variable. Instead of using a macro to
: "abbreviate" a long variable name, use a reference. Instead of
: using a macro to conditionally compile code ... well, don't do
: that at all (except, of course, for the #define guards to prevent
: double inclusion of header files). It makes testing much more
: difficult.
: The following usage pattern will avoid many problems with macros;
: if you use macros, follow it whenever possible:
: Don't define macros in a .h file.
: #define macros right before you use them, and #undef them right
: after.
: Do not just #undef an existing macro before replacing it with your
: own; instead, pick a name that's likely to be unique.
: Try not to use macros that expand to unbalanced C++ constructs, or
: at least document that behavior well.
: 使用macro時最好跟隨命名原則(naming)
: 使用全部大寫及底線,而且最好在名稱就把自己的目的說清楚
: You're not really going to define a macro, are you? If you do,
: they're like this: MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
: Please see the description of macros; in general macros should not
: be used. However, if they are absolutely needed, then they should
: be named like enum value names with all capitals and underscores.
: #define ROUND(x) ...<--我覺得這個也不夠好,如果別人用了同樣的名字就糟了!
: #define PI_ROUNDED 3.0
: macro會存在是因為它有魔法般的威力來幫你程式碼變更簡潔
: 但是就如同operator overloading一樣,太過魔幻(指簡潔就能達到目的)的語法
: 常常會讓debugging還有trace code變得異常困難
: 儘管如此我還是用玩火的心態想試試macro啦XD
: 我的對應之道是採三個步驟:
: 1.
: 還在建構功能時以方便trace code為目的
: 所以macro只有設IDX_PTR和IDX_END
: 因為使用後會比_readBufPtr-_readBuf更好讀,也更好trace
: 2.
: 先把功能一個一個全部完成並通過測試
: 等到全部弄完後,才去想說要如何簡化美化程式碼
: (也就是先寫eazy and dirty solution)
: 如果中間你就開始想實驗奇怪的macro,最後程式碼可能會需要砍掉重鍊吧..
: 3.
: 評估一下到底是哪幾個地方程式碼重複最嚴重
: 然後再想該用哪一種簡化方式
: 這次作業的特色是需要計數的地方很多
: 剛好用macro比我所知的其他方法都合適(就計數而言)
: macro的命名真的很重要,千萬不要怕長
: 盡量以能夠完全表達這個macro的動作為命名原則
: 這樣一方面不容易跟其他的程式人員的命名打架
: 另一方面我覺得撰寫程式都是盡量以讓人更好讀為目標
: 而不是拼命讓字數變少或是用一大堆的註解來取代
: 還有,如果有回傳值這樣的動作,盡量用function而不是macro
: 泡神就有舉個例子:x*x的macro丟進++i會變成++i*++i..
: 我的廢話好多喔XD
: 結論是:我覺得這次作業我會用macro只是特例而已
說實在的, 大部分的 C++ users 都會莫名奇妙的排斥 MACROs...
也許覺得那是 C 的遺毒吧~~~ :)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.21.241
1F:推 dryman:推~又多學到了好幾種作法!!! 10/22 13:00
2F:推 dryman:其實不只C++,有很多語言都不太推macro 10/22 13:04
3F:→ dryman:像是python, ruby, shell script, java(有外掛)... 10/22 13:05
4F:→ dryman:倒是perl有macro,不過他的程式特色本來就是走魔幻語法就是 10/22 13:06
5F:推 mymaydayya:perl魔幻語法 XD 10/22 20:38