作者holydc (のヮの)
看板Soft_Job
標題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: 哈哈,我就知道會有人搬組語出來講。 04/26 05:56
→ suhorng: 優化過後呢? 04/26 10:48
推 xxtuoo: 我玩了一下VC release build..還真的比較短..不過這年頭多 04/26 15:43
→ xxtuoo: 數決..老人認命服眾.. 04/26 15:43
推 TobyH4cker: 可惡,被搶先了XD 04/26 15:53
我也試了一下
http://i.imgur.com/D4XfZ8Q.jpg
迴圈部分是完全一樣的,差別在於他們計算位址的方式
strcpy2 在迴圈開始前多了一段計算 dst 跟 src 的 offset
為什麼會有這個差別我也不知道,大概跟 inline 的方式有關
順便試了 g++ (4.8.2, g++ -std=c++11 -O2 main.cpp)
http://i.imgur.com/k1BxyzY.jpg
這就是只有順序不同了
我自己判斷可讀性標準是"一行裡面做的事情越少越好讀"這樣啦
不曉得大家認為的好讀是如何
※ 編輯: holydc (111.248.194.201), 04/26/2015 17:40:30
推 pttworld: 一"行"改一個statement較好理解。 04/26 19:24
這我有想過
但有人會在一行塞好幾個 statement,我覺得這也會造成閱讀困難
所以後來還是決定以行為單位
※ 編輯: holydc (111.248.194.201), 04/26/2015 20:32:53
→ Masakiad: 複雜的statements 可以抽象成一個概念的function/method 04/27 01:41
→ Masakiad: 比較好閱讀,好過通通塞一行或多行 04/27 01:41
→ Masakiad: 其實我的想法是code就是說故事啊。聽者不需要知道的細節 04/27 01:48
→ Masakiad: 都用一個function name描述我會覺得好懂。 04/27 01:48
→ Masakiad: 有點像是用function name寫註解的感覺 04/27 01:50
推 FukadaKyoko: 推有實驗精神 04/27 13:51