青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

#ant

The dreams in which I'm dying are the best I've ever had...

strlen源碼剖析

學(xué)習(xí)高效編程的有效途徑之一就是閱讀高手寫(xiě)的源代碼,CRT(C/C++ Runtime Library)作為底層的函數(shù)庫(kù),實(shí)現(xiàn)必然高效。恰好手中就有g(shù)libc和VC的CRT源代碼,于是挑了一個(gè)相對(duì)簡(jiǎn)單的函數(shù)strlen研究了一下,并對(duì)各種實(shí)現(xiàn)作了簡(jiǎn)單的效率測(cè)試。

strlen的函數(shù)原形如下:

??????size_t strlen(const char *str);

strlen返回str中字符的個(gè)數(shù),其中str為一個(gè)以'\0'結(jié)尾的字符串(a null-terminated string)。

1. 簡(jiǎn)單實(shí)現(xiàn)
如果不管效率,最簡(jiǎn)單的實(shí)現(xiàn)只需要4行代碼:

1?size_t?strlen_a(const?char?* str)?{
2?????size_t?length?=?0
;
3?????while?(*str++
)
4?????????++
length;
5?????return
?length;
6?}

也許可以稍加改進(jìn)如下:

1?size_t?strlen_b(const?char?* str)?{
2?????const?char?*cp?=
?str;
3?????while?(*cp++
)
4?
????????;
5?????return?(cp?-?str?-?1
);
6?}

2. 高效實(shí)現(xiàn)
很顯然,標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)肯定不會(huì)如此簡(jiǎn)單,上面的strlen_a以及strlen_b都是一次判斷一個(gè)字符直到發(fā)現(xiàn)'\0'為止,這是非常低效的。比較高效的實(shí)現(xiàn)如下(在這里WORD表示計(jì)算機(jī)中的一個(gè)字,不是WORD類型):
(1) 一次判斷一個(gè)字符直到內(nèi)存對(duì)齊,如果在內(nèi)存對(duì)齊之前就遇到'\0'則直接return,否則到(2);
(2) 一次讀入并判斷一個(gè)WORD,如果此WORD中沒(méi)有為0的字節(jié),則繼續(xù)下一個(gè)WORD,否則到(3);
(3) 到這里則說(shuō)明WORD中至少有一個(gè)字節(jié)為0,剩下的就是找出第一個(gè)為0的字節(jié)的位置然后return。


NOTE:
數(shù)據(jù)對(duì)齊(data alignment),是指數(shù)據(jù)所在的內(nèi)存地址必須是該數(shù)據(jù)長(zhǎng)度的整數(shù)倍,這樣CPU的存取速度最快。比如在32位的計(jì)算機(jī)中,一個(gè)WORD為4 byte,則WORD數(shù)據(jù)的起始地址能被4整除的時(shí)候CPU的存取效率比較高。CPU的優(yōu)化規(guī)則大概如下:對(duì)于n字節(jié)(n = 2,4,8...)的元素,它的首地址能被n整除才能獲得最好的性能。

為了便于下面的討論,這里假設(shè)所用的計(jì)算機(jī)為32位,即一個(gè)WORD為4個(gè)字節(jié)。下面給出在32位計(jì)算機(jī)上的C語(yǔ)言實(shí)現(xiàn)(假設(shè)unsigned long為4個(gè)字節(jié)):

?1?typedef?unsigned?long ?ulong;
?2?

?3?size_t?strlen_c(const?char?* str)?{
?4?

?5?????const?char?* char_ptr;
?6?????const?ulong?*
longword_ptr;
?7?
????register?ulong?longword,?magic_bits;
?8?

?9?????for?(char_ptr?= ?str;?((ulong)char_ptr?
10?????????&?(sizeof(ulong)?-?1))?!=?0
;
11?????????++
char_ptr)?{
12?????????if?(*char_ptr?==?'\0'
)
13?????????????return?char_ptr?-
?str;
14?
????}
15?

16?????longword_ptr?=?(ulong* )char_ptr;
17?

18?????magic_bits?=?0x7efefeffL ;
19?

20?????while?(1 )?{
21?

22?????????longword?=?*longword_ptr++ ;
23?

24?????????if?((((longword?+?magic_bits)?^?~longword)?&?~magic_bits)?!=?0 )?{
25?

26?????????????const?char?*cp?=?(const?char*)(longword_ptr?-?1 );
27?
????????????
28?????????????if?(cp[0]?==?0
)
29?????????????????return?cp?-
?str;
30?????????????if?(cp[1]?==?0
)
31?????????????????return?cp?-?str?+?1
;
32?????????????if?(cp[2]?==?0
)
33?????????????????return?cp?-?str?+?2
;
34?????????????if?(cp[3]?==?0
)
35?????????????????return?cp?-?str?+?3
;
36?
????????}
37?
????}
38?}

3. 源碼剖析
上面給出的C語(yǔ)言實(shí)現(xiàn)雖然不算特別復(fù)雜,但也值得花點(diǎn)時(shí)間來(lái)弄清楚,先看9-14行:
for?(char_ptr?=?str;?((ulong)char_ptr?&?(sizeof(ulong)?-?1))?!=?0;?++char_ptr)?{
????
if?(*char_ptr?==?'\0'
)
????????
return?char_ptr?-
?str;
}

上面的代碼實(shí)現(xiàn)了數(shù)據(jù)對(duì)齊,如果在對(duì)齊之前就遇到'\0'則可以直接return char_ptr - str;

第16行將longword_ptr指向數(shù)據(jù)對(duì)齊后的首地址

longword_ptr?=?(ulong*)char_ptr;

第18行給magic_bits賦值(在后面會(huì)解釋這個(gè)值的意義)
magic_bits?=?0x7efefeffL;

第22行讀入一個(gè)WORD到longword并將longword_ptr指向下一個(gè)WORD
longword?=?*longword_ptr++;

第24行的if語(yǔ)句是整個(gè)算法的核心,該語(yǔ)句判斷22行讀入的WORD中是否有為0的字節(jié)
if?((((longword?+?magic_bits)?^?~longword)?&?~magic_bits)?!=?0)
if語(yǔ)句中的計(jì)算可以分為如下3步:
(1) longword + magic_bits
其中magic_bits的二進(jìn)制表示如下:
??????????????????b3??????b2?????? b1?????? b0
??????????????
31------------------------------->0

??magic_bits:?
01111110?11111110?11111110?11111111
magic_bits中的31,24,16,8這些bits都為0,我們把這幾個(gè)bits稱為holes,注意在每個(gè)byte的左邊都有一個(gè)hole。

檢測(cè)0字節(jié):
如果longword 中有一個(gè)字節(jié)的所有bit都為0,則進(jìn)行加法后,從這個(gè)字節(jié)的右邊的字節(jié)傳遞來(lái)的進(jìn)位都會(huì)落到這個(gè)字節(jié)的最低位所在的hole上,而從這個(gè)字節(jié)的最高位則永遠(yuǎn)不會(huì)產(chǎn)生向左邊字節(jié)的hole的進(jìn)位。則這個(gè)字節(jié)左邊的hole在進(jìn)行加法后不會(huì)改變,由此可以檢測(cè)出0字節(jié);相反,如果longword中所有字節(jié)都不為0,則每個(gè)字節(jié)中至少有1位為1,進(jìn)行加法后所有的hole都會(huì)被改變。

為了便于理解,請(qǐng)看下面的例子:
??????????????????b3??????b2?????? b1?????? b0
??????????????31------------------------------->0
??longword:???XXXXXXXX?XXXXXXXX?
00000000?XXXXXXXX
+?magic_bits:?01111110?11111110?11111110?11111111
上面longword中的b1為0,X可能為0也可能為1。因?yàn)閎1的所有bit都為0,而從b0傳遞過(guò)來(lái)的進(jìn)位只可能是0或1,很顯然b1永遠(yuǎn)也不會(huì)產(chǎn)生進(jìn)位,所以加法后longword的第16 bit這個(gè)hole不會(huì)變。

(2)? ^ ~longword
這一步取出加法后longword中所有未改變的bit。

(3)? & ~magic_bits
最后取出longword中未改變的hole,如果有任何hole未改變則說(shuō)明longword中有為0的字節(jié)。

根據(jù)上面的描述,如果longword中有為0的字節(jié),則if中的表達(dá)式結(jié)果為非0,否則為0。
NOTE:
如果b3為10000000,則進(jìn)行加法后第31 bit這個(gè)hole不會(huì)變,這說(shuō)明我們無(wú)法檢測(cè)出b3為10000000的所有WORD。值得慶幸的是用于strlen的字符串都是ASCII標(biāo)準(zhǔn)字符,其值在0-127之間,這意味著每一個(gè)字節(jié)的第一個(gè)bit都為0。因此上面的算法是安全的。

一旦檢測(cè)出longword中有為0的字節(jié),后面的代碼只需要找到第一個(gè)為0的字節(jié)并返回相應(yīng)的長(zhǎng)度就OK:
const?char?*cp?=?(const?char*)(longword_ptr?-?1);

if?(cp[0]?==?0
)
????
return?cp?-
?str;
if?(cp[1]?==?0
)
????
return?cp?-?str?+?1
;
if?(cp[2]?==?0
)
????
return?cp?-?str?+?2
;
if?(cp[3]?==?0
)
????
return?cp?-?str?+?3;

4. 另一種實(shí)現(xiàn)
?1?size_t?strlen_d(const?char?*str)?{
?2?

?3?????const?char?*char_ptr;
?4?????const?ulong?*
longword_ptr;
?5?
????register?ulong?longword,?himagic,?lomagic;
?6?

?7?????for?(char_ptr?=?str;?((ulong)char_ptr?
?8?????????&?(sizeof(ulong)?-?1))?!=?0
;
?9?????????++
char_ptr)?{
10?????????if?(*char_ptr?==?'\0'
)
11?????????????return?char_ptr?-
?str;
12?
????}
13?

14?????longword_ptr?=?(ulong*)char_ptr;
15?

16?????himagic?=?0x80808080L;
17?????lomagic?=?0x01010101L
;
18?

19?????while?(1)?{
20?

21?????????longword?=?*longword_ptr++;
22?

23?????????if?(((longword?-?lomagic)?&?himagic)?!=?0)?{
24?

25?????????????const?char?*cp?=?(const?char*)(longword_ptr?-?1);
26?
????????????
27?????????????if?(cp[0]?==?0
)
28?????????????????return?cp?-
?str;
29?????????????if?(cp[1]?==?0
)
30?????????????????return?cp?-?str?+?1
;
31?????????????if?(cp[2]?==?0
)
32?????????????????return?cp?-?str?+?2
;
33?????????????if?(cp[3]?==?0
)
34?????????????????return?cp?-?str?+?3
;
35?
????????}
36?
????}
37?}
上面的代碼與strlen_c基本一樣,不同的是:
magic_bits換成了himagic和lomagic
himagic?=?0x80808080L;
lomagic?
=?0x01010101L;
以及?if語(yǔ)句變得比較簡(jiǎn)單了
if?(((longword?-?lomagic)?&?himagic)?!=?0)

if語(yǔ)句中的計(jì)算可以分為如下2步:
(1) longword - lomagic
himagic和lomagic的二進(jìn)制表示如下:
????????????????b3??????b2???????b1???????b0
????????????
31------------------------------->0

??himagic:??10000000?10000000?
10000000?10000000
? lomagic:??00000001 00000001?00000001?00000001

在這種方法中假設(shè)所有字符都是ASCII標(biāo)準(zhǔn)字符,其值在0-127之間,因此longword總是如下形式:
????????????????b3??????b2???????b1???????b0
????????????
31------------------------------->0

??longword:?
0XXXXXXX 0XXXXXXX?0XXXXXXX?0XXXXXXX

檢測(cè)0字節(jié):
如果longword 中有一個(gè)字節(jié)的所有bit都為0,則進(jìn)行減法后,這個(gè)字節(jié)的最高位一定會(huì)從0變?yōu)?;相反,如果longword中所有字節(jié)都不為0,則每個(gè)字節(jié)中至少有1位為1,進(jìn)行減法后這個(gè)字節(jié)的最高位依然為0。

?(2)? & himagic
這一步取出每個(gè)字節(jié)最高位的1,如果有任意字節(jié)最高位為1則說(shuō)明longword中有為0的字節(jié)。

根據(jù)上面的描述,如果longword中有為0的字節(jié),則if中的表達(dá)式結(jié)果為非0,否則為0。

5. 匯編實(shí)現(xiàn)
VC CRT的匯編實(shí)現(xiàn)與前面strlen_c算法類似

??1?????????page????,132
??2?????????title???strlen?-?return?the?length?of?a?null-terminated?string
??3?;***

??4?;strlen.asm?-?contains?strlen()?routine
??5?
;
??6?
;???????Copyright?(c)?Microsoft?Corporation.?All?rights?reserved.
??7?
;
??8?
;Purpose:
??9?;???????strlen?returns?the?length?of?a?null-
terminated?string,
?10?;???????not?including?the?null?byte
?itself.
?11?
;
?12?;*******************************************************************************

?13?
?14?????????.xlist
?15?
????????include?cruntime.inc
?16?
????????.list
?17?

?18?page
?19?;***

?20?;strlen?-?return?the?length?of?a?null-terminated?string
?21?
;
?22?
;Purpose:
?23?
;???????Finds?the?length?in?bytes?of?the?given?string,?not?including
?24?;???????the?final?null
?character.
?25?
;
?26?
;???????Algorithm:
?27?;???????int?strlen?(const?char?*
?str)
?28?
;???????{
?29?;???????????int?length?=?0
;
?30?
;
?31?;???????????while(?*str++
?)
?32?;???????????????????++
length;
?33?
;
?34?;???????????return
(?length?);
?35?
;???????}
?36?
;
?37?
;Entry:
?38?;???????const?char?*?str?-
?string?whose?length?is?to?be?computed
?39?
;
?40?
;Exit:
?41?;???????EAX?=?length?of?the?string?"str",?exclusive?of?the?final?null?byte

?42?;
?43?
;Uses:
?44?
;???????EAX,?ECX,?EDX
?45?
;
?46?
;Exceptions:
?47?
;
?48?;*******************************************************************************

?49?
?50?????????CODESEG
?51?

?52?????????public??strlen
?53?

?54?strlen??proc?\
?55?????????buf:ptr?byte

?56?
?57?????????OPTION?PROLOGUE:NONE,?EPILOGUE:NONE
?58?

?59?????????.FPO????(?0,?1,?0,?0,?0,?0?)
?60?

?61?string??equ?????[esp?+?4]
?62?

?63?????????mov?????ecx,string??????????????;?ecx?->?string
?64?????????test????ecx,3???????????????????;?test?if?string?is?aligned?on?32
?bits
?65?????????je??????short
?main_loop
?66?

?67?str_misaligned:
?68?????????;?simple?byte
?loop?until?string?is?aligned
?69?????????mov?????al,byte
?ptr?[ecx]
?70?????????add?????ecx,1

?71?????????test????al,al
?72?????????je??????short
?byte_3
?73?????????test????ecx,3

?74?????????jne?????short?str_misaligned
?75?

?76?????????add?????eax,dword?ptr?0?????????;?5?byte?nop?to?align?label?below
?77?

?78?????????align???16??????????????????????;?should?be?redundant
?79?

?80?main_loop:
?81?????????mov?????eax,dword?ptr?[ecx]?????;?read?4
?bytes
?82?
????????mov?????edx,7efefeffh
?83?
????????add?????edx,eax
?84?????????xor?????eax,-1

?85?????????xor?????eax,edx
?86?????????add?????ecx,4

?87?????????test????eax,81010100h
?88?????????je??????short
?main_loop
?89?????????;?found?zero?byte
?in?the?loop
?90?????????mov?????eax,[ecx?-?4
]
?91?????????test????al,al???????????????????;?is?it?byte?0

?92?????????je??????short?byte_0
?93?????????test????ah,ah???????????????????;?is?it?byte?1

?94?????????je??????short?byte_1
?95?????????test????eax,00ff0000h???????????;?is?it?byte?2

?96?????????je??????short?byte_2
?97?????????test????eax,0ff000000h??????????;?is?it?byte?3

?98?????????je??????short?byte_3
?99?????????jmp?????short?main_loop?????????;?taken?if?bits?24-30
?are?clear?and?bit
100?????????????????????????????????????????;?31
?is?set
101?

102?byte_3:
103?????????lea?????eax,[ecx?-?1
]
104?
????????mov?????ecx,string
105?
????????sub?????eax,ecx
106?
????????ret
107?
byte_2:
108?????????lea?????eax,[ecx?-?2
]
109?
????????mov?????ecx,string
110?
????????sub?????eax,ecx
111?
????????ret
112?
byte_1:
113?????????lea?????eax,[ecx?-?3
]
114?
????????mov?????ecx,string
115?
????????sub?????eax,ecx
116?
????????ret
117?
byte_0:
118?????????lea?????eax,[ecx?-?4
]
119?
????????mov?????ecx,string
120?
????????sub?????eax,ecx
121?
????????ret
122?

123?strlen??endp
124?

125?????????end

6. 測(cè)試結(jié)果
為了對(duì)上述各種實(shí)現(xiàn)的效率有一個(gè)大概的認(rèn)識(shí),我在VC8和GCC下分別進(jìn)行了測(cè)試,測(cè)試時(shí)均采用默認(rèn)優(yōu)化方式。下面是在GCC下運(yùn)行幾百萬(wàn)次后的結(jié)果(在VC8下的運(yùn)行結(jié)果與此相似):
strlen_a
--------------------------------------------------

???????
1:????????515?ticks?????????0.515?seconds
???????
2:????????375?ticks?????????0.375
?seconds
???????
3:????????375?ticks?????????0.375
?seconds
???????
4:????????375?ticks?????????0.375
?seconds
???????
5:????????375?ticks?????????0.375
?seconds
???total:???????
2015?ticks?????????2.015
?seconds
?average:????????
403?ticks?????????0.403
?seconds
--------------------------------------------------


strlen_b
--------------------------------------------------
???????
1:????????360?ticks??????????0.36?seconds
???????
2:????????390?ticks??????????0.39
?seconds
???????
3:????????375?ticks?????????0.375
?seconds
???????
4:????????360?ticks??????????0.36
?seconds
???????
5:????????375?ticks?????????0.375
?seconds
???total:???????
1860?ticks??????????1.86
?seconds
?average:????????
372?ticks?????????0.372
?seconds
--------------------------------------------------


strlen_c
--------------------------------------------------
???????
1:????????187?ticks?????????0.187?seconds
???????
2:????????172?ticks?????????0.172
?seconds
???????
3:????????187?ticks?????????0.187
?seconds
???????
4:????????187?ticks?????????0.187
?seconds
???????
5:????????188?ticks?????????0.188
?seconds
???total:????????
921?ticks?????????0.921
?seconds
?average:????????
184?ticks????????0.1842
?seconds
--------------------------------------------------


strlen_d
--------------------------------------------------
???????
1:????????172?ticks?????????0.172?seconds
???????
2:????????187?ticks?????????0.187
?seconds
???????
3:????????172?ticks?????????0.172
?seconds
???????
4:????????187?ticks?????????0.187
?seconds
???????
5:????????188?ticks?????????0.188
?seconds
???total:????????
906?ticks?????????0.906
?seconds
?average:????????
181?ticks????????0.1812
?seconds
--------------------------------------------------


strlen
--------------------------------------------------
???????
1:????????187?ticks?????????0.187?seconds
???????
2:????????172?ticks?????????0.172
?seconds
???????
3:????????188?ticks?????????0.188
?seconds
???????
4:????????172?ticks?????????0.172
?seconds
???????
5:????????187?ticks?????????0.187
?seconds
???total:????????
906?ticks?????????0.906
?seconds
?average:????????
181?ticks????????0.1812
?seconds
--------------------------------------------------

源代碼:點(diǎn)擊下載

posted on 2007-10-12 13:19 螞蟻終結(jié)者 閱讀(31156) 評(píng)論(34)  編輯 收藏 引用 所屬分類: The Annotated CRT Sources

Feedback

# re: strlen源碼剖析 2007-09-26 19:29 msdn47

果然很快,效率高啊  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-26 21:29 hi

(2) ^ ~longword
這一步取出加法后longword中所有未改變的bit。

======================================

這個(gè)什么意思?  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 08:19 螞蟻終結(jié)者

可能我說(shuō)的不夠清楚,看下面的例子:
                   b3      b2       b1       b0
               31------------------------------->0
     longword: 00001001 00011000 00000000 00001100
+  magic_bits: 01111110 11111110 11111110 11111111
          sum: 10001000 00010110 11111111 00001011
^   ~longword: 11110110 11100111 11111111 11110011
            a: 01111110 11110001 00000000 11111000
& ~magic_bits: 10000001 00000001 00000001 00000000
       result: 00000000 00000001 00000000 00000000
sum = longword + magic_bits;
a = sum ^ ~longword;
即用sum與longword逐位比較,如果有某個(gè)位相同,就說(shuō)這個(gè)位在加法后未改變,這樣在a中為1的位就是未改變的。
 
result = a & ~magic_bits;
得到未改變的hole位,從上例可以看出第16 bit這個(gè)hole加法后未改變,這樣就檢測(cè)出了0字節(jié)。
 
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 08:28 wangmuy

贊啊!以前不懂的今天終于看懂了!  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析[未登錄](méi) 2007-09-27 08:42 漂舟

樓主剖析得全面,頂 !  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 08:52 Yong Sun

只能檢測(cè)0~127,是個(gè)問(wèn)題,最好能兼容0~255,有部分制表符和擴(kuò)展字符位于這個(gè)區(qū)域。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 09:06 螞蟻終結(jié)者

實(shí)際上0~255都能檢測(cè)出來(lái)的:
if (cp[0== 0)
    
return cp - str;
if (cp[1== 0)
    
return cp - str + 1;
if (cp[2== 0)
    
return cp - str + 2;
if (cp[3== 0)
    
return cp - str + 3;
如果上面的語(yǔ)句執(zhí)行完還沒(méi)有return,則會(huì)繼續(xù)下一次循環(huán),這樣還是能檢測(cè)到在if語(yǔ)句中漏掉的128~255,只不過(guò)效率上會(huì)有所損失。如果要檢測(cè)0~255之間的字符,strlen_c比strlen_d要好。因?yàn)閟trlen_c只會(huì)漏掉這樣的WORD:
    10000000 XXXXXXXX XXXXXXXX XXXXXXXX
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 09:23 k120

為了便于下面的討論,這里假設(shè)所用的計(jì)算機(jī)為32位,即一個(gè)WORD為4個(gè)字節(jié)?呵呵,筆誤吧?
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 09:35 螞蟻終結(jié)者

Sorry,我不該用WORD這個(gè)單詞。我說(shuō)的WORD在這里表示計(jì)算機(jī)中的一個(gè)字長(zhǎng),不是一般為2個(gè)字節(jié)的WORD類型。
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 10:32 Yong Sun

另外,是否有endian的問(wèn)題呢?  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 10:39 Yong Sun

想了想,應(yīng)該沒(méi)有,呵呵  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 11:16 螞蟻終結(jié)者

c語(yǔ)言的版本不會(huì)有endian的問(wèn)題,如果用匯編就需要注意了。
假設(shè)有4個(gè)連續(xù)的字節(jié)abcd,現(xiàn)在要找出其中的第一個(gè)0字節(jié):
1. 在PowerPC這種big-endian的計(jì)算機(jī)上,將這4個(gè)字節(jié)讀到寄存器中依然是
abcd,從左到右找到最左邊的0字節(jié)就OK了。

2. 在X86這種little-endian的計(jì)算機(jī)上,將這4個(gè)字節(jié)讀到寄存器中就會(huì)變成
dcba,這就需要從右到左找到最右邊的0字節(jié)。

可以看出,上面VC的匯編實(shí)現(xiàn)是針對(duì)X86計(jì)算機(jī)的。
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-09-27 12:51 ∑x

如果能做到這樣的分析,還有什么能學(xué)不會(huì)?!  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-10-12 16:36 Minidx全文檢索

幾天前看過(guò)的文章怎么又跑前面來(lái)了?!  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-10-12 16:43 螞蟻終結(jié)者

我也奇怪,就改了一下,再發(fā)布就變了。連日期都變了,郁悶。。。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-10-12 17:04 Minidx全文檢索

不過(guò)是好文章,多看幾遍也不錯(cuò)~  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-10-13 09:24 erran

強(qiáng)!希望這樣的好文不要鏈接失效!o(∩_∩)o...  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-11-02 13:04 really green

for (char_ptr = str; ((ulong)char_ptr
& (sizeof(ulong) - 1)) != 0 ;
++ char_ptr) {
if (*char_ptr == '\0' )
return char_ptr - str;
}

我比較菜,這里就看不明白:
((ulong)char_ptr
& (sizeof(ulong) - 1)) != 0 ;

(ulong)char_ptr 這個(gè)轉(zhuǎn)換把一個(gè) char * 轉(zhuǎn)成 ulong 會(huì)發(fā)生什么事情?  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-11-02 19:28 really green

想了想這個(gè)問(wèn)題問(wèn)得挺幼稚,我理解 (ulong)char_ptr應(yīng)該得到一個(gè)ulong的值,這個(gè)值就是指針char_ptr的值。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-11-04 09:35 螞蟻終結(jié)者

you gotta it!  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-12-04 05:39 福福

如果有中文字符,這個(gè)是不是有問(wèn)題
if (((longword - lomagic) & himagic) != 0)  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-12-05 19:39 螞蟻終結(jié)者

@福福
中文字符應(yīng)該用wcslen才對(duì),strlen是用來(lái)處理單字節(jié)字符串的。
詳細(xì)描述請(qǐng)看MSDN:
However, strlen interprets the string as a single-byte character string, so its return value is always equal to the number of bytes, even if the string contains multibyte characters. wcslen is a wide-character version of strlen; the argument of wcslen is a wide-character string and the count of characters is in wide (two-byte) characters.
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-12-27 14:01 Fox

幾年沒(méi)動(dòng)過(guò)匯編了,看了代碼,有種耳目一新的感覺(jué)~~~~~~~~  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2007-12-31 17:44 Sunky

感謝博主的精彩剖析。
感覺(jué)到我不會(huì)的東西太多了
由此堅(jiān)定了我看GNU C的決心
謝謝  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2008-09-07 16:11 star

博主的文章允許轉(zhuǎn)載么?
昨天看glibc里的注釋覺(jué)得云里霧里
今天看了博主的文章,突然覺(jué)得豁然開(kāi)朗啊 ;-)
還有想問(wèn)一個(gè)問(wèn)題 glibc里是這樣處理64位的
if (sizeof (longword) > 4)
{
/* 64-bit version of the magic. */
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
himagic = ((himagic << 16) << 16) | himagic;
lomagic = ((lomagic << 16) << 16) | lomagic;
}
為什么不一次就移32位呢?  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2008-09-07 19:54 螞蟻終結(jié)者

@star
歡迎轉(zhuǎn)載,轉(zhuǎn)載當(dāng)然是沒(méi)有問(wèn)題的,畢竟寫(xiě)文章就是能讓更多的人看到!

為什么不一次就移32位呢?
我也不太清楚,可能就其中注釋所說(shuō):
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
只是為了避免warn吧呵呵!  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2008-11-07 11:42 test

似乎CRT庫(kù)的這種寫(xiě)法有點(diǎn)越界訪問(wèn)的意思,呵呵。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2009-03-18 17:08 123

@福福
strlen算法在處理中文時(shí)不會(huì)出問(wèn)題,關(guān)鍵點(diǎn)在后面的if(cp[?]==0)。
不過(guò)處理中文時(shí)效率會(huì)跟最簡(jiǎn)單的strlen一樣。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2009-04-29 14:32 uestc

分析得很清楚,寫(xiě)得也很詳細(xì),贊一個(gè)。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2009-06-05 14:06 宋兵乙

for (char_ptr = str; ((ulong)char_ptr
& (sizeof(ulong) - 1)) != 0 ;
++ char_ptr) {
if (*char_ptr == '\0' )
return char_ptr - str;
}

如上的代碼我看不懂了,我的分析如下,麻煩各位高手指出錯(cuò)誤。
sizeof(ulong)-1等于3,也就是二進(jìn)制的0000 0011,于是想要跳出for循環(huán),只需char_ptr的最后兩位是0即可。而每次for循環(huán)時(shí),char_ptr執(zhí)行了++操作,由于char_ptr是指向char的指針,因此每次++應(yīng)該是增加一個(gè)char的長(zhǎng)度就是8。表現(xiàn)在二進(jìn)制上就是倒數(shù)第4位增加1,而后兩位是不會(huì)變化的。故得出結(jié)論若char_ptr的初始值不滿足最后兩位是0,那for就永遠(yuǎn)是死循環(huán)了。。

求各位指出上述論證錯(cuò)誤在哪。另外,我沒(méi)明白此例中內(nèi)存對(duì)齊到滿足哪種條件才能提高代碼效率。  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2009-06-08 11:51 螞蟻終結(jié)者

@宋兵乙
“由于char_ptr是指向char的指針,因此每次++應(yīng)該是增加一個(gè)char的長(zhǎng)度就是8”
看來(lái)你對(duì)指針運(yùn)算還不太了解,建議好好復(fù)習(xí)一下指針部分。
授人魚(yú)不如授人漁呵呵  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2009-10-29 11:31 似水之心

學(xué)習(xí),謝謝分享  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2010-07-31 20:38 hoodlum1980

不錯(cuò)。我今天反匯編看到strlen的匯編代碼一直覺(jué)得很奇怪,
沒(méi)搞懂這幾句話在干什么。。。看了這篇文章很有幫助。
  回復(fù)  更多評(píng)論   

# re: strlen源碼剖析 2010-11-07 14:37 郭龍

學(xué)習(xí),學(xué)習(xí),時(shí)刻關(guān)注。  回復(fù)  更多評(píng)論   


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99riav1国产精品视频| 国产精品色网| 国产精品99久久久久久www| 欧美激情一区二区三区| 欧美电影打屁股sp| 亚洲国产婷婷香蕉久久久久久| 欧美好骚综合网| 日韩视频一区二区三区在线播放| 99热精品在线| 亚洲欧美综合另类中字| 久久国产精品色婷婷| 久久久午夜视频| 欧美精品1区2区| 国产毛片精品视频| 亚洲欧美国产视频| 亚洲日本中文字幕区| 亚洲一区久久| 久久久久久网| 99国产精品一区| 欧美一区二区三区在线播放| 蜜桃av久久久亚洲精品| 国产精品久久福利| 亚洲激情电影在线| 欧美亚洲综合在线| 亚洲激情一区| 午夜精品福利电影| 欧美精品在欧美一区二区少妇| 国产精品自拍在线| 日韩一区二区免费高清| 久久综合综合久久综合| 在线中文字幕一区| 欧美成人官网二区| 激情一区二区| 性欧美精品高清| 亚洲免费电影在线| 免费观看一区| 国内精品视频在线播放| 午夜欧美大尺度福利影院在线看 | 久久久亚洲高清| 国产精品久久久久久久久久久久久久| 亚洲国产aⅴ天堂久久| 久久精品日韩一区二区三区| 一本到高清视频免费精品| 麻豆久久久9性大片| 国产一区久久| 午夜亚洲激情| 一级日韩一区在线观看| 欧美日韩亚洲91| 一本高清dvd不卡在线观看| 欧美va天堂| 久久久免费观看视频| 黄色av成人| 蜜臀91精品一区二区三区| 久久精品综合网| 狠狠色丁香婷婷综合久久片| 久久久精品五月天| 久久精品国产v日韩v亚洲| 国产在线拍偷自揄拍精品| 久久精品国产亚洲精品| 欧美一级二级三级蜜桃| 国产亚洲电影| 久久在线精品| 久久综合久久久久88| 亚洲电影中文字幕| 亚洲高清视频在线| 欧美精品电影在线| 亚洲永久视频| 欧美一区成人| 一区视频在线播放| 亚洲国产高清在线| 欧美日韩一区自拍| 有坂深雪在线一区| 国产欧美在线视频| 久久伊人精品天天| 老色批av在线精品| 亚洲理论电影网| 99精品视频免费| 国产欧美精品在线| 欧美成人免费小视频| 欧美精品一区三区在线观看| 亚洲欧美日韩国产一区二区| 欧美一区二区| 99成人免费视频| 亚洲女女做受ⅹxx高潮| 尤物九九久久国产精品的分类| 亚洲国产一区二区精品专区| 国产精品成人一区二区网站软件| 久久久久久国产精品mv| 欧美电影免费观看高清| 亚洲欧美视频在线| 老司机免费视频久久| 亚洲影院色无极综合| 久久九九99视频| 亚洲五月六月| 久久久久99| 亚洲午夜精品视频| 久久综合色播五月| 欧美影院在线| 欧美日韩高清一区| 免费亚洲一区二区| 国产伦理一区| av成人免费在线| 最新日韩欧美| 欧美一区网站| 亚洲综合首页| 欧美精品福利在线| 米奇777在线欧美播放| 国产精品乱人伦中文| 亚洲精品国产精品国自产观看浪潮| 国产日韩欧美在线播放| 亚洲免费大片| 日韩视频免费在线| 美日韩在线观看| 久久亚洲国产成人| 国产午夜精品麻豆| 亚洲免费影视| 亚洲欧美国产视频| 欧美色另类天堂2015| 亚洲国产欧美精品| 亚洲国产成人av好男人在线观看| 午夜视频一区二区| 欧美亚洲综合另类| 国产精品久久久久久久久久久久久久 | 亚洲破处大片| 一区在线播放视频| 欧美与欧洲交xxxx免费观看| 欧美一区国产在线| 国产精品亚洲综合色区韩国| 亚洲麻豆一区| 9i看片成人免费高清| 欧美精品色一区二区三区| 欧美福利在线| 亚洲黄色免费电影| 欧美成人午夜| 欧美精品三级| 久久久久久久久岛国免费| 国产精品高清在线观看| 一本一本a久久| 中文欧美在线视频| 欧美视频在线一区| 亚洲视频在线观看| 亚洲欧美日韩国产综合| 国产精品日日摸夜夜摸av| 亚洲一区二区三区在线| 欧美亚洲尤物久久| 好吊日精品视频| 麻豆精品精华液| 亚洲国产成人精品视频| 99日韩精品| 国产精品午夜久久| 久久久xxx| 亚洲高清电影| 亚洲一区二区在线播放| 国产精品一区免费观看| 久久国产精品久久w女人spa| 欧美激情在线有限公司| 亚洲一区二区视频在线| 国产亚洲在线| 欧美 日韩 国产一区二区在线视频| 亚洲精品乱码久久久久久黑人| 亚洲一级在线| 狠狠久久婷婷| 国产精品xvideos88| 久久gogo国模裸体人体| 亚洲精品乱码久久久久| 久久se精品一区精品二区| 亚洲经典视频在线观看| 国产精品色网| 欧美国产日韩精品免费观看| 亚洲欧美国产视频| 欧美激情视频在线免费观看 欧美视频免费一 | 欧美 日韩 国产在线 | 亚洲欧美三级在线| 欧美电影免费观看高清完整版| 亚洲视频中文字幕| 一区在线观看| 国产精品视频免费观看| 男女激情久久| 午夜亚洲视频| 日韩亚洲综合在线| 欧美v日韩v国产v| 欧美一区2区视频在线观看| 亚洲人成网站色ww在线| 国产手机视频一区二区| 欧美日韩亚洲三区| 蜜臀va亚洲va欧美va天堂| 亚洲欧美韩国| av成人国产| 亚洲精品美女在线| 欧美高清视频| 久久综合国产精品台湾中文娱乐网| 中文国产一区| 亚洲伦理在线观看| 亚洲国产精品女人久久久| 国产日韩在线不卡| 国产精品美女久久久久av超清 | 欧美国产日韩一区二区三区| 久久国产精品久久久久久电车| 亚洲午夜精品一区二区| 一区二区三区高清在线观看|