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

#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 螞蟻終結者 閱讀(31124) 評論(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

贊?。∫郧安欢慕裉旖K于看懂了!  回復  更多評論   

# 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>
            亚洲性图久久| aa级大片欧美| 久久综合九色综合欧美狠狠| 欧美一区二区三区啪啪| 激情欧美国产欧美| 亚洲高清视频中文字幕| 日韩亚洲一区二区| 欧美中在线观看| 欧美综合国产| 久久精品91| 亚洲二区在线| 日韩特黄影片| 国产一区白浆| 亚洲黄色精品| 国产精品欧美在线| 欧美成人网在线| 欧美日韩第一区日日骚| 久久国产福利国产秒拍| 另类综合日韩欧美亚洲| 亚洲特色特黄| 久久在线免费| 亚洲自拍偷拍视频| 久久久久久综合| 亚洲一区二区欧美日韩| 欧美在线观看天堂一区二区三区| 亚洲黄色av一区| 亚洲视频一二三| 亚洲高清网站| 性欧美xxxx大乳国产app| 亚洲精品久久视频| 欧美一区二区三区婷婷月色| 99视频精品| 久久久久久**毛片大全| 亚洲尤物在线| 欧美好吊妞视频| 久久综合成人精品亚洲另类欧美| 欧美少妇一区二区| 欧美激情第一页xxx| 国产一区二区三区黄| 99国产精品国产精品久久| 狠狠色香婷婷久久亚洲精品| 亚洲少妇在线| 一本一本久久| 欧美精品久久久久久久久久| 久久综合伊人77777| 国产精品一区=区| 99一区二区| 一本一本a久久| 欧美h视频在线| 欧美gay视频激情| 韩国女主播一区二区三区| 亚洲综合视频网| 亚洲欧美日韩一区二区在线| 欧美极品在线观看| 免费日韩av| 亚洲电影在线看| 久久亚洲精选| 免费在线观看日韩欧美| 黑人中文字幕一区二区三区| 午夜视频精品| 欧美在线视频观看免费网站| 国产精品羞羞答答| 午夜综合激情| 久久精品青青大伊人av| 国产日韩av高清| 午夜精品成人在线| 久久久久久欧美| 在线播放日韩专区| 鲁大师成人一区二区三区| 欧美成人蜜桃| 亚洲免费激情| 欧美三日本三级三级在线播放| 亚洲欧美日韩爽爽影院| 亚洲一区二区精品在线| 亚洲在线播放电影| 国产精品一区二区黑丝| 亚洲欧美日韩成人高清在线一区| 久久九九国产精品| 国产在线乱码一区二区三区| 久久久久久久久久久久久女国产乱| 久久嫩草精品久久久久| 亚洲第一搞黄网站| 欧美激情中文字幕一区二区| 在线亚洲欧美视频| 欧美中文在线观看| 亚洲国产精品第一区二区| 欧美福利视频在线| 亚洲色图在线视频| 久久青青草原一区二区| 91久久黄色| 国产精品美女久久久久久久| 久久av一区| 亚洲人在线视频| 久久精品首页| 亚洲精品视频二区| 国产欧美韩日| 欧美黄色影院| 午夜国产一区| 亚洲人成人99网站| 久久激情综合网| 999在线观看精品免费不卡网站| 国产精品成人aaaaa网站| 久久国产精品久久久久久电车| 亚洲高清精品中出| 久久免费黄色| 亚洲一区三区视频在线观看| 影音先锋日韩精品| 国产精品国产三级国产专区53 | 影音先锋亚洲视频| 欧美亚一区二区| 欧美激情按摩在线| 久久精品系列| 亚洲欧美日本在线| 日韩一级在线| 亚洲人成绝费网站色www| 久久蜜桃av一区精品变态类天堂| 野花国产精品入口| 在线免费日韩片| 狠狠色狠狠色综合日日小说| 国产精品久久久久久久一区探花| 欧美/亚洲一区| 久久精品国产99国产精品| 99精品视频一区| 91久久国产综合久久| 蜜臀a∨国产成人精品| 欧美一区久久| 午夜精品网站| 亚洲一区二区在线免费观看| 亚洲精品美女久久7777777| 狠狠色狠狠色综合人人| 国产午夜精品久久久| 国产精品捆绑调教| 欧美婷婷在线| 欧美日韩专区在线| 欧美三级视频在线观看| 欧美国产日本| 欧美精品高清视频| 欧美精品一级| 欧美日韩精品免费观看视一区二区| 老牛嫩草一区二区三区日本| 久久精品女人天堂| 久久久久久国产精品一区| 欧美一区三区二区在线观看| 欧美一区二区三区播放老司机 | 亚洲电影专区| 欧美性猛交视频| 午夜精品久久久久久久99水蜜桃| 亚洲在线不卡| 亚洲欧美日韩在线| 亚洲欧美清纯在线制服| 亚洲欧美另类综合偷拍| 久久国产精品第一页| 久久综合电影一区| 欧美大色视频| 欧美手机在线| 韩国精品一区二区三区| 亚洲高清成人| 宅男噜噜噜66一区二区| 亚洲自拍偷拍麻豆| 久久精品99| 欧美激情影音先锋| 日韩一级黄色av| 久久er精品视频| 欧美国产日韩二区| 国产精品久久久久毛片大屁完整版| 国产欧美亚洲日本| 亚洲成色777777女色窝| 一区二区三区日韩精品视频| 欧美一区二区视频在线| 美日韩精品视频| 日韩系列欧美系列| 久久aⅴ国产欧美74aaa| 欧美激情 亚洲a∨综合| 国产欧美一区二区三区视频| 亚洲日本va在线观看| 先锋影音国产精品| 欧美国产高潮xxxx1819| 日韩西西人体444www| 久久久精品五月天| 欧美日韩国产a| 国内精品久久久久久久果冻传媒 | 国产乱码精品一区二区三区忘忧草| 精品99一区二区| 亚洲影院免费观看| 亚洲高清三级视频| 欧美一区免费| 国产精品看片资源| 日韩午夜在线视频| 久久久国产91| 亚洲综合成人在线| 欧美激情一区二区三区在线| 黄页网站一区| 午夜亚洲精品| 亚洲精品国精品久久99热一| 久久久久欧美精品| 国产精品一区视频| 欧美va天堂在线| 夜夜爽www精品| 男女视频一区二区| 国产一区二区三区四区五区美女|