顯示廣告
隱藏 ✕
看板 terievv
作者 terievv (terievv)
標題  標題  [閒聊] i++ is undefined behavior?
時間 2015-04-26 Sun. 07:56:31


看板 Soft_Job
作者 ah7675 (阿懋)
標題 [閒聊] i++ is undefined behavior?
時間 Fri Apr 24 23:22:09 2015


最近因為同事在code review時表示 i++會隨編譯器實作而有不同行為

所以要求我不要用這種寫法,到這邊應該很多人會說:"沒錯啊,這你都不懂?"

關鍵在於他舉的例子是這樣的

i=10;
val = array[i++];
val equals array[10] or array[11]?

我整個傻住了,我的理解是,答案絕對是val=array[10]

而隨編譯器會變化的地方是,在該expression/statement所構成的

數個指令中"遞增"的時機可能不同,所以如果在一個expression中存取i

兩次以上會造成未定義行為

但suffix increament operator必定是先return再遞增

請問我的理解才是錯的嗎?

那GLIBC裡的strcmp實作也是不可靠的嗎?
https://fossies.org/dox/glibc-2.21/string_2strcmp_8c_source.html

還有另一個例子是說const global variable is better than Macro??

理由是global variable只有一份、用再多次也只是reference同一份

但是macro假設被使用10次就會造成code size增加10倍

用來舉例的型別是int

這也是顛覆了我一直以來的觀念,讓我相當震撼

我應該趕快請前輩喝飲料順便多請教他,還是趁試用期還沒過趕快離職?

請各位給我一些意見,感謝!

--
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 175.181.142.174
※ 文章代碼(AID): #1LEb-bDg (Soft_Job)
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429888933.A.36A.html
descent: 寫個反例就可以知道結果。show me the code1F 04/24 23:34
ah7675: 請問反例是指?2F 04/24 23:38
descent: const global variable 比 macro 大3F 04/24 23:47
atst2: 用const global variable是對的, 但理由不是size4F 04/25 00:01
loveme00835: i++當然不是先 return 再遞增, 是先遞增再 return5F 04/25 00:02
atst2: 更多人選擇使用static const,為的是提供型別安全6F 04/25 00:02
loveme00835: 舊值給你7F 04/25 00:02
tjjh89017: i++那個你講的應該是對的8F 04/25 00:03
tjjh89017: 等等,好像L大講的比較正確一點@@
ah7675: 感謝L大指教 不過我的重點在return回來的值 不過表達不當10F 04/25 00:08
ah7675: 還有他會因為編譯器不同而造成return遞增後的值回來嗎?
ah7675: atst2說的我知道 感謝回覆
atst2:13F 04/25 00:12
koka813: 就我所知,第一個就像你講的那樣~14F 04/25 00:13
atst2: The value obtained by applying a postfix ++ is the15F 04/25 00:23
atst2: value that the operand had before applying the operator
atst2: 舊版的c++standard是這樣說的,新的不知道有沒有改.
saladim: 多次"寫讀"同一變數才是undefined吧? 是不是記錯啦?18F 04/25 00:42
saladim: marco這個說法也怪怪的 應該先問他macro怎麼定義 然後用
saladim: const global variable有一用意是型別安全 且macro置換常
saladim: 會有置換出乎意料跟同名macro造成的bug
PUTOUCHANG: 叫他不要打高空, 怎樣的情況會造成語意錯誤說來聽聽22F 04/25 00:46
ah7675: macro vs global variable指的是常量 所以我才特指int23F 04/25 01:17
ah7675: type safe這點是在c++適用 c就沒差了XD
saladim: macro定義是常量的話....用variable開-O該不會也是被換成25F 04/25 01:41
saladim: 一個常量吧 也就是都是像: int newVar = 12 之類的 XDDDD
saladim: 以上猜測啦 不要打我(畢竟還要多產生取variable值的code)
v7q4: 實務上很少會用那種裝神弄鬼的寫法...是想搞死自己嗎XDD28F 04/25 02:00
csfgsj: 就是有這種吃飽太閒的人29F 04/25 08:23
pttdocc: 你那同事一知半解  30F 04/25 20:48
remember318: 系統資源有少到需要斤斤計較幾K的記憶體消耗嗎?31F 04/26 01:18
看板 Soft_Job
作者 developers (勤能補拙)
標題 Re: [閒聊] i++ is undefined behavior?
時間 Sat Apr 25 01:36:31 2015


※ 引述《ah7675 (阿懋)》之銘言:
: 最近因為同事在code review時表示 i++會隨編譯器實作而有不同行為
: 所以要求我不要用這種寫法,到這邊應該很多人會說:"沒錯啊,這你都不懂?"
: 關鍵在於他舉的例子是這樣的
: i=10;
: val = array[i++];
: val equals array[10] or array[11]?
: 我整個傻住了,我的理解是,答案絕對是val=array[10]
: 而隨編譯器會變化的地方是,在該expression/statement所構成的
: 數個指令中"遞增"的時機可能不同,所以如果在一個expression中存取i
: 兩次以上會造成未定義行為
: 但suffix increament operator必定是先return再遞增
: 請問我的理解才是錯的嗎?
: 那GLIBC裡的strcmp實作也是不可靠的嗎?
: https://fossies.org/dox/glibc-2.21/string_2strcmp_8c_source.html
: 還有另一個例子是說const global variable is better than Macro??
: 理由是global variable只有一份、用再多次也只是reference同一份
: 但是macro假設被使用10次就會造成code size增加10倍
: 用來舉例的型別是int
: 這也是顛覆了我一直以來的觀念,讓我相當震撼
: 我應該趕快請前輩喝飲料順便多請教他,還是趁試用期還沒過趕快離職?
: 請各位給我一些意見,感謝!

第二個問題:
Effective C++ Item2: Prefer consts, enums, and inlines to #defines
簡單的列一下書上所提的#define的4個缺點,順便複習一下
舉例 #define ASPECT_RATIO 1.653
1. The symbolic name ASPECT_RATIO may never be seen by compilers;
   it may be removed by the preprocessor before the source code ever
   gets to a compiler.
2. The preprocessor's blind substitution of the marco name could
   result in multiple copies in your object code.
3. Marco breaks class encapsulation.
4. When using marcos, you have to remember to parenthesize all the
   arguments in the marco body.

第一個問題:
post increment 實做的結果就是先把原值存一個copy,increment i,再回傳copy
其中increment i這個動作是用++i來做的
所以可以說 i++ is implemented in terms of ++i
只要這個核心概念是不變的,i++就是會回傳遞增前的值,而++i則是回傳遞增後
的值
補充:
關於你提到的undefined behavior,要視是回傳值的形態而定
如果回傳形態是const by value,或reference to const,而你又想再去改變它的值
就會產生問題
例如i++的回傳形態是const by value,因此寫i++++就會產生compiler error
這其實是用來提醒使用者避免這樣的用法
(可參考More Effective C++ Item6)

希望有回答到你的問題^^



--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 106.1.232.252
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429896994.A.283.html
※ 編輯: developers (106.1.232.252), 04/25/2015 02:28:10
yushiung: 其實就只是 left value 跟 right value 的不同而已1F 04/25 12:33
ah7675: 我完全同意在C++使用global variable相對於Macro的優點2F 04/25 13:33
ah7675: 不過我的原文是不同意code size觀點 跟我在"程式設計師的
ah7675: 自我修養"理解的完全不同啊
yakimo: 一個拿時間換空間 一個拿空間換時間吧...5F 04/25 17:38
看板 Soft_Job
作者 pttworld (批踢踢世界)
標題 Re: [閒聊] i++ is undefined behavior?
時間 Sat Apr 25 05:27:01 2015


觀念上,++operand和operand++在同一個statement才會的。
然而仍取決於實作的compiler。
不存在那種寫法比較高明或要逼死誰?!
寫法是對programmer來說的,
對機器沒差。
※ 引述《ah7675 (阿懋)》之銘言:
: 最近因為同事在code review時表示 i++會隨編譯器實作而有不同行為
: 所以要求我不要用這種寫法,到這邊應該很多人會說:"沒錯啊,這你都不懂?"
: 關鍵在於他舉的例子是這樣的
: i=10;
: val = array[i++];
: val equals array[10] or array[11]?
: 我整個傻住了,我的理解是,答案絕對是val=array[10]
: 而隨編譯器會變化的地方是,在該expression/statement所構成的
: 數個指令中"遞增"的時機可能不同,所以如果在一個expression中存取i
: 兩次以上會造成未定義行為
: 但suffix increament operator必定是先return再遞增
: 請問我的理解才是錯的嗎?
: 那GLIBC裡的strcmp實作也是不可靠的嗎?
: https://fossies.org/dox/glibc-2.21/string_2strcmp_8c_source.html
: 還有另一個例子是說const global variable is better than Macro??
: 理由是global variable只有一份、用再多次也只是reference同一份
: 但是macro假設被使用10次就會造成code size增加10倍
: 用來舉例的型別是int
: 這也是顛覆了我一直以來的觀念,讓我相當震撼
: 我應該趕快請前輩喝飲料順便多請教他,還是趁試用期還沒過趕快離職?
: 請各位給我一些意見,感謝!

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.139.64.168
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429910824.A.BD3.html
Feis: 這觀念有點問題1F 04/25 07:11
Feis: 有很多情況都會是 undefined behaviour
Feis: 而大部份情況下寫出 undefined behaviour 就是不應該的
testPtt: 知道自己在做什麼記得註解就行了4F 04/25 08:03
fr3ak: 樓上: 十個需要加注解的地方有九個不如改成直白的寫法來的5F 04/25 09:27
fr3ak: 好.
remmurds: 就是有人喜歡賣弄一堆華而不實的寫法7F 04/25 12:19
Bencrie: 推樓上 XD8F 04/25 12:58
看板 Soft_Job
作者 ah7675 (阿毛)
標題 Re: [閒聊] i++ is undefined behavior?
時間 Sat Apr 25 13:30:54 2015


※ 引述《pttworld (批踢踢世界)》之銘言:
: 觀念上,++operand和operand++在同一個statement才會的。
: 然而仍取決於實作的compiler。
: 不存在那種寫法比較高明或要逼死誰?!
: 寫法是對programmer來說的,
: 對機器沒差。
: ※ 引述《ah7675 (阿懋)》之銘言:
: : 最近因為同事在code review時表示 i++會隨編譯器實作而有不同行為
: : 所以要求我不要用這種寫法,到這邊應該很多人會說:"沒錯啊,這你都不懂?"
: : 關鍵在於他舉的例子是這樣的
: : i=10;
: : val = array[i++];
: : val equals array[10] or array[11]?
: : 我整個傻住了,我的理解是,答案絕對是val=array[10]
: : 而隨編譯器會變化的地方是,在該expression/statement所構成的
: : 數個指令中"遞增"的時機可能不同,所以如果在一個expression中存取i
: : 兩次以上會造成未定義行為
: : 但suffix increament operator必定是先return再遞增
: : 請問我的理解才是錯的嗎?
: : 那GLIBC裡的strcmp實作也是不可靠的嗎?
: : https://fossies.org/dox/glibc-2.21/string_2strcmp_8c_source.html
: : 還有另一個例子是說const global variable is better than Macro??
: : 理由是global variable只有一份、用再多次也只是reference同一份
: : 但是macro假設被使用10次就會造成code size增加10倍
: : 用來舉例的型別是int
: : 這也是顛覆了我一直以來的觀念,讓我相當震撼
: : 我應該趕快請前輩喝飲料順便多請教他,還是趁試用期還沒過趕快離職?
: : 請各位給我一些意見,感謝!

經過一串討論我又更震驚了......

原來glibc裡strcmp那種寫法對大多數人來說是華而不實

艱澀難懂又容易產生bug,平常真的沒人用這種寫法嗎?

本身是做embedded的,從bootloader到kernel到上層ap都有經驗(Linux)

學生時代也有Windows開發經驗(VS2008 MFC/Qt)

經常遊走在C與C++之間,最近則是因為改SublimeText plugin在學python XD

雖然不敢說是高手,但也看過一些open source的code

busybox/dhcp, xbmc, openwrt framework, Qt

++operator對於字串操作是極其常見(其他暫不提)

所以我一直以為這是很稀鬆平常而且基礎的寫法

這是第一次遇到有人告知我這種寫法不准用,老實說有點難接受

我完全理解"不要為了語法的漂亮而使用少見難懂的語法"

我自己也常這樣告誡自己,可是"難懂"的分界到底在哪裡?

同樣一句話由Google工程師或是學生說出來可以說是完完全全兩個世界

因為兩者對"難"的定義可說完全不一樣!



另外再問一個:
function pointer/function object也是怪物嗎?

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 175.181.142.174
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429939856.A.D00.html
onear: 這種寫法的優點除了少一行程式之外,我想不到有其他優點..1F 04/25 14:12
onear: 搬到下一行去++不好嗎?
Ting1024: 就是咩,幹嘛搞複雜,3F 04/25 14:15
ah7675: 所以大家都不用c libraray裡的function 自己改用好理解又4F 04/25 14:30
ah7675: 簡單的實作?
Masakiad: 寫Code跟寫文章一樣是給人看的啊,能夠好好理解,不容出6F 04/25 15:08
Masakiad: 錯是很重要的。沒錯,文言文有精深的學問,現在沒人用
Masakiad: 文言文聊天吧。
Masakiad: Function point很少場合用,比如在我開發自家script eng
Masakiad: ine時使用
x000032001: ++這種大一就應該懂的水題 有什麼難看懂的11F 04/25 15:18
x000032001: 不如把++刪掉 都用i=i+1好了 超簡單
pttworld: 難懂是看不懂的說的,但你無法讓每個人好懂。最簡單的13F 04/25 15:39
pttworld: 方法就是讓別人看不到,比如library或api,僅外露讓人容
pttworld: 易使用和呼叫的介面。
strlen: 基本市我給自己寫程式的終極目標,是讓初學程式的學生都能16F 04/25 15:42
strlen: 看了之後略知一二,但又不犧牲效能以及架構的需求
strlen: 當然這每個人都不同,但如果有人跟我抱怨++寫法難懂,我會
strlen: 改用更簡單的寫法
lashante: 除非你永遠都要單打獨鬥,不然team work就是要遷就伙伴20F 04/25 15:51
lashante: 要嘛就花力氣把你的伙伴都教到和你一樣smart
lashante: 要不一開始就寫那種不用教,也能讓人一眼完全理解的code
lashante: 你覺得哪個比較費力?
final01: 說真的你懂原理就用,不懂就不要用啊!24F 04/25 16:09
final01: 事實上你的狀況是看了ㄧ堆專案其實你跟本就不懂....
final01: 然後在這到處質疑人...
ah7675: 請問我不懂什麼? 我也從沒說我什麼都懂啊? 本來每個人27F 04/25 16:18
ah7675: 就有懂或不懂的東西 但是因為不懂就不准用才是我質疑的點
ah7675: 今天假設真的是業界標準是這樣 讓新鮮人知道一下有壞處嗎
ah7675: 如果因為不懂繼承或組合 就要求擴充的時候只准寫全新的
ah7675: 這樣真的有人可以接受嗎?
Masakiad: 不知道原po有沒看過clean code. 到底怎樣算難懂,怎樣可32F 04/25 16:34
Masakiad: 讀性算不好。書上有提供一些經驗跟理由。雖然我只認同80
Masakiad: %但我覺得啟發蠻多的。
GoalBased: a = i++; 改寫成 i++; a=i; 其實沒有很難..35F 04/25 16:35
HowLeeHi: 樓上好像寫反了吧..36F 04/25 16:37
ah7675: 樓上的兩個寫法a是不一樣的喔37F 04/25 16:37
GoalBased: XD..38F 04/25 16:38
ah7675: @Masakiad 所以glibc那個code算是閱讀性不好的嗎?39F 04/25 16:38
GoalBased: 工作就是團隊嘛..真的不能接受換個公司不是滿好的嗎40F 04/25 16:39
ah7675: 我覺得書很多本 網路資料也很多 關於可讀性還有變數命名41F 04/25 16:39
ah7675: 看法歧異也很多
ah7675: 我是擔心不管去哪裡都會要求不准用者種寫法 所以上來問問
GoalBased: 我以前老闆也說過 i++ 不好懂,雖然他只是舉個例子啦44F 04/25 16:41
GoalBased: 他想表達的是用普遍一點的寫法就法,之後我就離職了
sing10407: 樓上做了最好的示範 …程式還是以好讀易懂為主46F 04/25 16:46
ah7675: 可是他之後就離職了耶XD47F 04/25 16:47
berton1679: function pointer 在module化又要保持效能 可考慮48F 04/25 17:05
saladim: 寫法好不好要看背後的理由 不是在有名的lib或是framework49F 04/25 17:53
saladim: 就是很正確的阿 甚至於open source也是一樣
saladim: 建議可以先去看程式競賽的code 會找到一些例子把++鑲嵌
saladim: 在statement難懂的例子 也可以有點感覺什麼叫好讀難讀
ah7675: glibc不有名吧.....只是很多作業系統裡面都是run他 這樣53F 04/25 17:56
saladim: 因為程式競賽的code不是用來維護的阿 是求快跟正確而已54F 04/25 17:56
saladim: glibc大家都知道不叫有名? 有名是指很多人知道
ah7675: 當作參考標準嗎? standard lib的說56F 04/25 17:57
saladim: 不是指大家大師稱讚57F 04/25 17:57
saladim: 我說的就是常用常run的lib也不一樣是好例子 如果你是要
saladim: 追求好維護好讀好懂的code
saladim: 打錯 不一樣是好例子 ==> 不一定是好例子
ah7675: 了解 所以standard lib不能當標準 那請問該舉什麼樣的例子61F 04/25 17:59
saladim: 其實各種寫法都有討論改進空間啦 看人是不是要堅持吧62F 04/25 18:00
ah7675: 來討論會比較恰當呢? 本來我想說用大家手邊的設備中使用63F 04/25 18:00
ah7675: 的核心元件應該是很好的例子 看來我還太淺了
saladim: 各種寫法好壞看理由 也沒有絕對好壞  理由上面各位大大65F 04/25 18:01
saladim: 有提了 看個人看了之後的想法吧  何況個人寫程式的脈絡
saladim: 跟環境都很不一樣 要去體會說在自己的工作內容中 這樣寫
saladim: 造成的結果跟影響.....不是說標準庫不能當標準  他當然可
saladim: 以當一個"例子"作為討論基準 不過不一樣要用: 標準庫都
saladim: 這麼寫 為什麼我不能這樣寫
saladim: 而且覺得討論++可不可以用 好像很模糊 也很難討論
azureblaze: std lib基本上裡頭的code不是以給人看為訴求的72F 04/25 18:07
saladim: 就好像討論能不能用? , if跟switch一樣73F 04/25 18:08
azureblaze: 行為都規範的很清楚,user通常不需要看他的實做74F 04/25 18:08
ah7675: 可是standard lib沒有維護的需要嗎? 他不是很多人協同合75F 04/25 18:09
ah7675: 合作而出來的產物 我之所以舉一些大型open source或是商業
ah7675: 作為例子 就是認為它符合各位所提的 "有維護需求", "多人
ah7675: 人開發"的前提 比起有些書可能著重個人觀點來得有討論基準
saladim: 我在想會不會太拘泥於++這個例子阿? 這個例子很難感受阿79F 04/25 18:14
saladim: 都有維護需求啦 當一個人長期看同一份code 都能看懂  但
saladim: 是很多人都有那種很痛苦trace code的經驗吧  我想你就用
saladim: 就盡量去寫++好了
saladim: 很多人的痛苦來自於要trace很多份不同人寫的不同領域產品
saladim: 又沒有三個月給你去仔細研究
saladim: 或許你可以試著去trace STL的code看看...一個禮拜...
ah7675: 這個每個人工作都需要啊 應該沒有人不需要的86F 04/25 18:19
ah7675: 開新project的時候不是就是拿不同team不同人的code portin
saladim: 至於書說是著重個人觀點 我是部份不同意 其實有些書的觀88F 04/25 18:20
ah7675: g + integration XD?89F 04/25 18:21
saladim: 點反而是收集眾多的案例 話說回來 還是要自己多想多體會90F 04/25 18:21
ah7675: 我是說“可能”是個人觀點91F 04/25 18:22
saladim: 我不是反對你的論點 我只是說明書其實也是收集案例的92F 04/25 18:22
saladim: 所以你拿到的code都輕鬆trace? 可以trace看看ACE阿?
saladim: trace MFC跟gtk framework....
saladim: 沒有啦 反正各自提觀點 若是大大的經驗都很輕鬆愉快 真的
saladim: 神手是沒有在怕什麼寫法的 yoco大大已經如此開釋過了
saladim: end!
ah7675: 我沒說trace code很輕鬆 但是不會因為++而覺得難懂98F 04/25 18:30
ah7675: 而且語法很難懂 跟這段code想要幹什麼很難懂是兩件事
saladim: 就說太拘泥++這個例子了 可能沒理解其他大大說的精神....100F 04/25 18:31
ah7675: 不是拘泥++ 只是用他當例子 光是macro又可以開另篇文101F 04/25 18:32
ah7675: 我同意閱讀性這件事 我自己也經常為此改換寫法
saladim: 痾..................ㄏㄏ 拉拉 魯魯........103F 04/25 18:33
ah7675: 其他版友提的我也了解104F 04/25 18:34
ah7675: 就好像 (a > min && a < max) 我會直接定義成叫做RANGE的
ah7675: macro 我並不是不了解可讀性的重要 我也不是寫code沒給人
ah7675: review過 前公司也有使用review系統 通常同事都會提些意見
ah7675: 可是從沒聽過有人反映某些基礎語法很難看不懂 所以不要用
shaform: 想要用類似 c 的語法,又不希望有 ++ expression 用法109F 04/25 19:22
shaform: 的話其實可以學 Go - https://golang.org
shaform: 不過其實也有連 ++ statement 都沒有的語言 0.0
看板 Soft_Job
作者 xxtuoo (看樣子是壞掉了 :~)
標題 Re: [閒聊] i++ is undefined behavior?
時間 Sat Apr 25 15:58:56 2015


※ 引述《ah7675 (阿毛)》之銘言:
: ++operator對於字串操作是極其常見(其他暫不提)
: 所以我一直以為這是很稀鬆平常而且基礎的寫法
: 這是第一次遇到有人告知我這種寫法不准用,老實說有點難接受
: 我完全理解"不要為了語法的漂亮而使用少見難懂的語法"
: 我自己也常這樣告誡自己,可是"難懂"的分界到底在哪裡?
: 同樣一句話由Google工程師或是學生說出來可以說是完完全全兩個世界
: 因為兩者對"難"的定義可說完全不一樣!
: 另外再問一個:
: function pointer/function object也是怪物嗎?


好久沒學新的東西了...果然是落伍了嗎?

void strcpy(char *s, char *t)
{
   while( (*s++ = *t++) != '\0') ;
}
先不論strcpy的安全性
這種++應該是很常見
想不到現在已經是不能被人接受的東西了

至於function pointer/funciton object
有再用有排序效果泛用容器的..set/map
傳一個funciton 或functor
當自己訂製元件的比較function
應該是很常用的寫法

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 58.114.104.237
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429948738.A.B31.html
ah7675: 同感 我工作三年左右 應該不算老人 所以聽到++不准用很1F 04/25 16:42
ah7675: 意外 = ="
bibo9901: 其實連 != '\0' 都不用3F 04/25 17:17
atst2: 有一派看法是,追求快速,簡短的事情,交給編譯器去做就好4F 04/25 18:14
atst2: 把語意分開,表示清楚,讓其他人不用多想幾秒才瞭解,會讓
atst2: 程式比較好維護.
descent: qsort 都需要 function pointer 了7F 04/25 18:16
descent: 我自己覺得很難看懂, 第一次看到時想好久。
看板 Soft_Job
作者 holydc (のヮの)
標題 Re: [閒聊] i++ is undefined behavior?
時間 Sun Apr 26 04:05:34 2015


※ 引述《xxtuoo (看樣子是壞掉了 :~)》之銘言:
: ※ 引述《ah7675 (阿毛)》之銘言:
: : ++operator對於字串操作是極其常見(其他暫不提)
: : 所以我一直以為這是很稀鬆平常而且基礎的寫法
: : 這是第一次遇到有人告知我這種寫法不准用,老實說有點難接受
: : 我完全理解"不要為了語法的漂亮而使用少見難懂的語法"
: : 我自己也常這樣告誡自己,可是"難懂"的分界到底在哪裡?
: : 同樣一句話由Google工程師或是學生說出來可以說是完完全全兩個世界
: : 因為兩者對"難"的定義可說完全不一樣!
: : 另外再問一個:
: : function pointer/function object也是怪物嗎?
: 好久沒學新的東西了...果然是落伍了嗎?
: void strcpy(char *s, char *t)
: {
:    while( (*s++ = *t++) != '\0') ;
: }
: 先不論strcpy的安全性
: 這種++應該是很常見
: 想不到現在已經是不能被人接受的東西了

void strcpy(char *dst, char *src) {
  while (*src != '\0') {
    *dst = *src;
    ++dst;
    ++src;
  }
  *dst = '\0';
}

這兩版翻成機器碼是幾乎一樣的
(來源:Visual Studio Express 2013 for Windows Desktop)

  while (*dst++ = *src++);          while (*src != '\0') {
mov    eax,dword ptr [dst]        mov    eax,dword ptr [src]
mov    ecx,dword ptr [src]        movsx  ecx,byte ptr [eax]
mov    dl,byte ptr [ecx]          test   ecx,ecx
mov    byte ptr [eax],dl          je     strcpy2+46h (01221476h)
mov    eax,dword ptr [dst]            *dst = *src;
mov    cl,byte ptr [eax]          mov    eax,dword ptr [dst]
mov    byte ptr [ebp-0C1h],cl     mov    ecx,dword ptr [src]
mov    edx,dword ptr [dst]        mov    dl,byte ptr [ecx]
add    edx,1                      mov    byte ptr [eax],dl
mov    dword ptr [dst],edx            ++dst;
mov    eax,dword ptr [src]        mov    eax,dword ptr [dst]
add    eax,1                      add    eax,1
mov    dword ptr [src],eax        mov    dword ptr [dst],eax
movsx  ecx,byte ptr [ebp-0C1h]        ++src;
test   ecx,ecx                    mov    eax,dword ptr [src]
je     strcpy1+52h (01221412h)    add    eax,1
jmp    strcpy1+1Eh (012213DEh)    mov    dword ptr [src],eax
                                    }
                                  jmp    strcpy2+1Eh (0122144Eh)
                                    *dst = '\0';
                                  mov    eax,dword ptr [dst]
                                  mov    byte ptr [eax],0

甚至可以發現第一版為了在 dst 遞增之前保留原本的值,還多了一段 mov
再從迴圈數來看,第一版因為整段做完才 test,賦值跟遞增都要 n + 1 次
第二版則是 n + 1 次賦值(包含迴圈外面的 *dst = '\0';) 跟 n 次遞增
姑且不論這種細微差異,第二版可讀性絕對大於第一版吧
第一版看的時候可能會想一下遞增的時間點,可能會想一下 * 跟 ++ 的優先度
更何況條件式裡面的 = 不管何時都會讓人毛毛的,想要多看他兩眼
第二版我是想不到什麼曖昧的地方

說不准這樣寫我也是覺得有點超過啦
但是在不影響效能的情況下,有更好讀的寫法,何樂而不為呢

: 至於function pointer/funciton object
: 有再用有排序效果泛用容器的..set/map
: 傳一個funciton 或functor
: 當自己訂製元件的比較function
: 應該是很常用的寫法

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.163.98.63
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1429992338.A.CF2.html
pttworld: 哈哈,我就知道會有人搬組語出來講。1F 04/26 05:56


--
※ 作者: terievv 時間: 2015-04-26 07:56:31
※ 看板: terievv 文章推薦值: 0 目前人氣: 0 累積人氣: 181 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇