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

#ant

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

strlen源碼剖析

學習高效編程的有效途徑之一就是閱讀高手寫的源代碼,CRT(C/C++ Runtime Library)作為底層的函數庫,實現必然高效。恰好手中就有glibc和VC的CRT源代碼,于是挑了一個相對簡單的函數strlen研究了一下,并對各種實現作了簡單的效率測試。

strlen的函數原形如下:

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

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

1. 簡單實現
如果不管效率,最簡單的實現只需要4行代碼:

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

也許可以稍加改進如下:

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

2. 高效實現
很顯然,標準庫的實現肯定不會如此簡單,上面的strlen_a以及strlen_b都是一次判斷一個字符直到發現'\0'為止,這是非常低效的。比較高效的實現如下(在這里WORD表示計算機中的一個字,不是WORD類型):
(1) 一次判斷一個字符直到內存對齊,如果在內存對齊之前就遇到'\0'則直接return,否則到(2);
(2) 一次讀入并判斷一個WORD,如果此WORD中沒有為0的字節,則繼續下一個WORD,否則到(3);
(3) 到這里則說明WORD中至少有一個字節為0,剩下的就是找出第一個為0的字節的位置然后return。


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

為了便于下面的討論,這里假設所用的計算機為32位,即一個WORD為4個字節。下面給出在32位計算機上的C語言實現(假設unsigned long為4個字節):

?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語言實現雖然不算特別復雜,但也值得花點時間來弄清楚,先看9-14行:
for?(char_ptr?=?str;?((ulong)char_ptr?&?(sizeof(ulong)?-?1))?!=?0;?++char_ptr)?{
????
if?(*char_ptr?==?'\0'
)
????????
return?char_ptr?-
?str;
}

上面的代碼實現了數據對齊,如果在對齊之前就遇到'\0'則可以直接return char_ptr - str;

第16行將longword_ptr指向數據對齊后的首地址

longword_ptr?=?(ulong*)char_ptr;

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

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

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

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

檢測0字節:
如果longword 中有一個字節的所有bit都為0,則進行加法后,從這個字節的右邊的字節傳遞來的進位都會落到這個字節的最低位所在的hole上,而從這個字節的最高位則永遠不會產生向左邊字節的hole的進位。則這個字節左邊的hole在進行加法后不會改變,由此可以檢測出0字節;相反,如果longword中所有字節都不為0,則每個字節中至少有1位為1,進行加法后所有的hole都會被改變。

為了便于理解,請看下面的例子:
??????????????????b3??????b2?????? b1?????? b0
??????????????31------------------------------->0
??longword:???XXXXXXXX?XXXXXXXX?
00000000?XXXXXXXX
+?magic_bits:?01111110?11111110?11111110?11111111
上面longword中的b1為0,X可能為0也可能為1。因為b1的所有bit都為0,而從b0傳遞過來的進位只可能是0或1,很顯然b1永遠也不會產生進位,所以加法后longword的第16 bit這個hole不會變。

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

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

根據上面的描述,如果longword中有為0的字節,則if中的表達式結果為非0,否則為0。
NOTE:
如果b3為10000000,則進行加法后第31 bit這個hole不會變,這說明我們無法檢測出b3為10000000的所有WORD。值得慶幸的是用于strlen的字符串都是ASCII標準字符,其值在0-127之間,這意味著每一個字節的第一個bit都為0。因此上面的算法是安全的。

一旦檢測出longword中有為0的字節,后面的代碼只需要找到第一個為0的字節并返回相應的長度就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. 另一種實現
?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語句變得比較簡單了
if?(((longword?-?lomagic)?&?himagic)?!=?0)

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

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

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

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

檢測0字節:
如果longword 中有一個字節的所有bit都為0,則進行減法后,這個字節的最高位一定會從0變為1;相反,如果longword中所有字節都不為0,則每個字節中至少有1位為1,進行減法后這個字節的最高位依然為0。

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

根據上面的描述,如果longword中有為0的字節,則if中的表達式結果為非0,否則為0。

5. 匯編實現
VC CRT的匯編實現與前面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. 測試結果
為了對上述各種實現的效率有一個大概的認識,我在VC8和GCC下分別進行了測試,測試時均采用默認優化方式。下面是在GCC下運行幾百萬次后的結果(在VC8下的運行結果與此相似):
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
--------------------------------------------------

源代碼:點擊下載

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

Feedback

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

果然很快,效率高啊  回復  更多評論   

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

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

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

這個什么意思?  回復  更多評論   

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

可能我說的不夠清楚,看下面的例子:
                   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逐位比較,如果有某個位相同,就說這個位在加法后未改變,這樣在a中為1的位就是未改變的。
 
result = a & ~magic_bits;
得到未改變的hole位,從上例可以看出第16 bit這個hole加法后未改變,這樣就檢測出了0字節。
 
  回復  更多評論   

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

贊??!以前不懂的今天終于看懂了!  回復  更多評論   

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

樓主剖析得全面,頂 !  回復  更多評論   

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

只能檢測0~127,是個問題,最好能兼容0~255,有部分制表符和擴展字符位于這個區域。  回復  更多評論   

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

實際上0~255都能檢測出來的:
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;
如果上面的語句執行完還沒有return,則會繼續下一次循環,這樣還是能檢測到在if語句中漏掉的128~255,只不過效率上會有所損失。如果要檢測0~255之間的字符,strlen_c比strlen_d要好。因為strlen_c只會漏掉這樣的WORD:
    10000000 XXXXXXXX XXXXXXXX XXXXXXXX
  回復  更多評論   

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

為了便于下面的討論,這里假設所用的計算機為32位,即一個WORD為4個字節?呵呵,筆誤吧?
  回復  更多評論   

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

Sorry,我不該用WORD這個單詞。我說的WORD在這里表示計算機中的一個字長,不是一般為2個字節的WORD類型。
  回復  更多評論   

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

另外,是否有endian的問題呢?  回復  更多評論   

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

想了想,應該沒有,呵呵  回復  更多評論   

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

c語言的版本不會有endian的問題,如果用匯編就需要注意了。
假設有4個連續的字節abcd,現在要找出其中的第一個0字節:
1. 在PowerPC這種big-endian的計算機上,將這4個字節讀到寄存器中依然是
abcd,從左到右找到最左邊的0字節就OK了。

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

可以看出,上面VC的匯編實現是針對X86計算機的。
  回復  更多評論   

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

如果能做到這樣的分析,還有什么能學不會?!  回復  更多評論   

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

幾天前看過的文章怎么又跑前面來了?!  回復  更多評論   

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

我也奇怪,就改了一下,再發布就變了。連日期都變了,郁悶。。。  回復  更多評論   

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

不過是好文章,多看幾遍也不錯~  回復  更多評論   

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

強!希望這樣的好文不要鏈接失效!o(∩_∩)o...  回復  更多評論   

# 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 這個轉換把一個 char * 轉成 ulong 會發生什么事情?  回復  更多評論   

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

想了想這個問題問得挺幼稚,我理解 (ulong)char_ptr應該得到一個ulong的值,這個值就是指針char_ptr的值。  回復  更多評論   

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

you gotta it!  回復  更多評論   

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

如果有中文字符,這個是不是有問題
if (((longword - lomagic) & himagic) != 0)  回復  更多評論   

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

@福福
中文字符應該用wcslen才對,strlen是用來處理單字節字符串的。
詳細描述請看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.
  回復  更多評論   

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

幾年沒動過匯編了,看了代碼,有種耳目一新的感覺~~~~~~~~  回復  更多評論   

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

感謝博主的精彩剖析。
感覺到我不會的東西太多了
由此堅定了我看GNU C的決心
謝謝  回復  更多評論   

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

博主的文章允許轉載么?
昨天看glibc里的注釋覺得云里霧里
今天看了博主的文章,突然覺得豁然開朗啊 ;-)
還有想問一個問題 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位呢?  回復  更多評論   

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

@star
歡迎轉載,轉載當然是沒有問題的,畢竟寫文章就是能讓更多的人看到!

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

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

似乎CRT庫的這種寫法有點越界訪問的意思,呵呵。  回復  更多評論   

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

@福福
strlen算法在處理中文時不會出問題,關鍵點在后面的if(cp[?]==0)。
不過處理中文時效率會跟最簡單的strlen一樣。  回復  更多評論   

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

分析得很清楚,寫得也很詳細,贊一個。  回復  更多評論   

# 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;
}

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

求各位指出上述論證錯誤在哪。另外,我沒明白此例中內存對齊到滿足哪種條件才能提高代碼效率。  回復  更多評論   

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

@宋兵乙
“由于char_ptr是指向char的指針,因此每次++應該是增加一個char的長度就是8”
看來你對指針運算還不太了解,建議好好復習一下指針部分。
授人魚不如授人漁呵呵  回復  更多評論   

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

學習,謝謝分享  回復  更多評論   

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

不錯。我今天反匯編看到strlen的匯編代碼一直覺得很奇怪,
沒搞懂這幾句話在干什么。。??戳诉@篇文章很有幫助。
  回復  更多評論   

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

學習,學習,時刻關注。  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美日韩在线一区| 亚洲国产小视频在线观看| 亚洲国产精品一区二区三区| 久久黄金**| 一区二区亚洲欧洲国产日韩| 老鸭窝毛片一区二区三区| 久久久久久国产精品mv| 亚洲激情六月丁香| 亚洲日本va在线观看| 国产精品高清在线| 久久精品国产综合| 蜜桃av一区二区| 99精品国产福利在线观看免费| 亚洲精品乱码久久久久久按摩观| 欧美日韩伊人| 久久精品五月| 欧美成人综合在线| 亚洲欧美综合| 久久一区激情| 亚洲自拍偷拍视频| 久久久久久久久伊人| 一本久道久久综合中文字幕| 亚洲一区影院| 最新日韩在线| 亚洲影院免费| 亚洲人成绝费网站色www| 亚洲小视频在线观看| 亚洲第一区在线| 亚洲一区二区成人| 亚洲人线精品午夜| 亚洲欧美日韩国产一区二区| 亚洲国产乱码最新视频| 亚洲免费影视| av成人免费在线| 久久久精品动漫| 亚洲欧美日韩在线一区| 免费成人高清在线视频| 欧美一区二区三区播放老司机| 美女黄色成人网| 日韩一级在线| 尤物九九久久国产精品的特点| 99国产精品99久久久久久粉嫩| 伊人成人在线视频| 亚洲一级在线观看| 中文av字幕一区| 嫩草影视亚洲| 久久网站热最新地址| 欧美午夜电影一区| 亚洲人人精品| 亚洲日本视频| 六月天综合网| 久久婷婷国产综合精品青草| 国产精品午夜电影| 一本色道久久综合狠狠躁篇怎么玩| 亚洲国产精品女人久久久| 久久成人一区| 久久精品一区二区三区中文字幕| 国产精品卡一卡二| 99国产精品久久久久久久| 99re6这里只有精品| 免费一区视频| 亚洲国产精品va| 91久久久亚洲精品| 免费国产自线拍一欧美视频| 女生裸体视频一区二区三区| 影音先锋日韩有码| 久久久久久高潮国产精品视| 蜜臀va亚洲va欧美va天堂| 狠狠色丁香久久婷婷综合_中| 欧美在线1区| 美乳少妇欧美精品| 亚洲国内精品在线| 欧美sm极限捆绑bd| 亚洲精品黄网在线观看| 99国产精品久久久久久久久久| 欧美岛国激情| 日韩亚洲一区在线播放| 亚洲综合精品自拍| 国产欧美日韩| 久久精品中文| 亚洲福利在线观看| 在线视频精品| 国产欧美日韩精品丝袜高跟鞋| 亚洲一区在线观看免费观看电影高清 | 亚洲男女自偷自拍| 国产欧美日韩另类视频免费观看| 香蕉亚洲视频| 免费高清在线视频一区·| 91久久精品国产91久久性色tv| 欧美精品18+| 亚洲在线黄色| 欧美黄色免费网站| 亚洲视频综合在线| 国产在线一区二区三区四区| 免费日韩成人| 亚洲视频欧美视频| 麻豆精品一区二区av白丝在线| 亚洲人体影院| 国产性做久久久久久| 欧美成人一区二区在线 | 噜噜噜在线观看免费视频日韩| 亚洲精选久久| 国产婷婷色一区二区三区四区| 老鸭窝91久久精品色噜噜导演| 99这里只有精品| 亚洲精品久久久久久一区二区 | 在线中文字幕一区| 蜜桃久久av一区| 亚洲综合欧美| 亚洲精品极品| 韩国精品久久久999| 欧美日韩亚洲网| 巨乳诱惑日韩免费av| 亚洲性视频网址| 91久久精品美女高潮| 久久精品视频在线看| 亚洲一区二区三区在线| 在线免费观看一区二区三区| 欧美私人啪啪vps| 美女黄色成人网| 欧美中文字幕在线| 亚洲淫片在线视频| 亚洲精品国产日韩| 欧美成人影音| 久久久久久久欧美精品| 西瓜成人精品人成网站| 亚洲美女淫视频| 亚洲高清在线精品| 国产综合激情| 国产亚洲一区二区在线观看| 国产精品成人aaaaa网站| 欧美国产三区| 欧美大片免费| 老司机精品视频网站| 久久久91精品国产一区二区三区| 亚洲欧美www| 亚洲一区二区三区高清| 一本一本a久久| 一区二区欧美精品| 亚洲精品国产系列| 亚洲日韩第九十九页| 欧美激情精品久久久| 欧美国内亚洲| 亚洲国产精品v| 亚洲人成免费| 日韩视频免费观看| 99在线|亚洲一区二区| 99视频国产精品免费观看| 亚洲欧洲日韩在线| 亚洲精品无人区| 一本久久a久久精品亚洲| 国产精品99久久不卡二区| 一本在线高清不卡dvd| 亚洲视频图片小说| 亚洲欧美日韩国产一区二区三区| 小黄鸭精品aⅴ导航网站入口 | 99re成人精品视频| 中文日韩在线| 欧美一区二区三区四区高清| 欧美一级免费视频| 巨乳诱惑日韩免费av| 欧美日韩mv| 国产精品一区一区三区| 韩国精品主播一区二区在线观看| 一区二区亚洲精品| 日韩一二三区视频| 亚洲欧美在线看| 免费久久99精品国产自在现线| 亚洲国产精品毛片| 亚洲亚洲精品三区日韩精品在线视频| 亚洲欧美成人综合| 美女福利精品视频| 国产精品久久久久久久久动漫| 国产一区91精品张津瑜| 亚洲精品一二| 久久精品国产91精品亚洲| 欧美国产大片| 亚洲尤物精选| 男女视频一区二区| 美女主播精品视频一二三四| 免费亚洲一区二区| 亚洲福利一区| 亚洲宅男天堂在线观看无病毒| 久久精品人人| 亚洲自拍偷拍视频| 亚洲欧美日产图| 亚洲欧美日韩爽爽影院| 久久精品视频播放| 欧美成人三级在线| 国产一区二区黄| 日韩小视频在线观看专区| 久久爱www.| 一本大道久久a久久精品综合| 亚欧成人精品| 欧美精品v日韩精品v韩国精品v| 欧美丝袜一区二区三区| 激情五月婷婷综合| 欧美一区二区三区免费大片| 男同欧美伦乱| 香蕉久久精品日日躁夜夜躁|