色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

字符串函數strlen的深入研究

C語言專家集中營 ? 來源:未知 ? 作者:李倩 ? 2018-03-26 16:01 ? 次閱讀

還記得初學C的時候,對于字符串操作一類函數的記憶顯得尤為深刻,各種考試會考strlen、strlen等函數的實現,到了畢業找工作,很多公司的筆試題里,也包含有strlen、strcpy等函數的實現。可見字符串操作類函數是受到了老師和公司出題者的青睞啊。那么本文就來研究一下strlen這個函數吧!

可能你這時已經在BS我了,心想就這么個東西,還需要研究的么。我能瞬間完成,于是你寫下了這段代碼:

[cpp]view plaincopy

intstrlen(constchar*str)

{

intlength=0;

while(*str++)

++length;

return(length);

}

哇!你還真快,真的瞬間寫下了這個簡潔精煉的strlen,不錯,你的C語言考題過關了,公司筆試也過了,值得恭喜。但是,似乎這么快就解決了問題,那本文要怎么進行下去呢?那就先分析一下你瞬間秒殺出來的這個strlen吧,她簡直太完美了,和MS的工程師們寫得如出一轍,總體看下來也就幾行代碼完事,那么,為啥這么幾行就能解決問題?還有沒有更優的方案?你靈機一動,又瞬間想出一種:

[cpp]view plaincopy

intstrlen(constchar*str)

{

constchar*ptr=str;

while(*str++)

;

return(str-ptr-1);

}

所謂代碼簡短不一定就是最優的,當然這里不能扯到軟件工程里去了,我們可以看出這兩種實現,str++是逐字節向后移動的,時間復雜度都是O(n),所以這個strlen可以很簡單的完成,那么更優的方案是什么呢?試想,如果能夠幾個字節一跳,不是能夠更快的完成求長度,不就降低了復雜度?先拭目以待吧。

本系列是為了剖析crt庫中intel模塊下的那些函數的,那么我們去找找那里面有沒有strlen的實現,呀!居然找到了,它就位于VC/crt/src/intel/strlen.asm里。打開看看,咦,有點暈。不過最亮眼的就是,在前面的注釋里,MS的工程師們寫了個“注釋版”的strlen,與你前面實現的strlen簡直是一摸一樣的。可是,它是注釋版的,不會編譯進程序運行。那么繼續看下面的匯編實現,代碼如下:

[cpp]view plaincopy

CODESEG

publicstrlen

strlenproc\

buf:ptrbyte

OPTIONPROLOGUE:NONE,EPILOGUE:NONE

.FPO(0,1,0,0,0,0)

stringequ[esp+4]

movecx,string;ecx->string

testecx,3;testifstringisalignedon32bits

jeshortmain_loop

str_misaligned:

;simplebyteloopuntilstringisaligned

moval,byteptr[ecx]

addecx,1

testal,al

jeshortbyte_3

testecx,3

jneshortstr_misaligned

addeax,dwordptr0;5bytenoptoalignlabelbelow

align16;shouldberedundant

main_loop:

moveax,dwordptr[ecx];read4bytes

movedx,7efefeffh

addedx,eax

xoreax,-1

xoreax,edx

addecx,4

testeax,81010100h

jeshortmain_loop

;foundzerobyteintheloop

moveax,[ecx-4]

testal,al;isitbyte0

jeshortbyte_0

testah,ah;isitbyte1

jeshortbyte_1

testeax,00ff0000h;isitbyte2

jeshortbyte_2

testeax,0ff000000h;isitbyte3

jeshortbyte_3

jmpshortmain_loop;takenifbits24-30areclearandbit

;31isset

byte_3:

leaeax,[ecx-1]

movecx,string

subeax,ecx

ret

byte_2:

leaeax,[ecx-2]

movecx,string

subeax,ecx

ret

byte_1:

leaeax,[ecx-3]

movecx,string

subeax,ecx

ret

byte_0:

leaeax,[ecx-4]

movecx,string

subeax,ecx

ret

strlenendp

end

只看主體部分的匯編代碼,我們進行逐句研究。

首先,是聲明了strlen的公共符號,以及strlen的函數參數等聲明,OPTION一句代碼是為了讓匯編程序不生成開始代碼和結束代碼(這個可以查閱相關文獻資料,這里不進行詳細解釋),下一句.FPO,是與堆棧指針省略(FramePointOmission)相關的,在MSDN里面的解釋如下:

FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame)

cdwLocals:Number of local variables, an unsigned 32 bit value.

cdwParams:Size of the parameters, an unsigned 16 bit value.

cbProlog:Number of bytes in the function prolog code, an unsigned 8 bit value.

cbRegs:Number of bytes in the function prolog code, an unsigned 8 bit value.

fUseBP:Indicates whether the EBP register has been allocated. either 0 or 1.

cbFrame:Indicates the frame type.在這里只需要關注第二個參數,它為1,表示有一個參數。strlen本身也就是一個參數。其他參數,看上面的英文注釋應該很簡單了,這里不作解釋。你也可以點擊這里查閱。

繼續向下,關注這三句:

[cpp]view plaincopy

stringequ[esp+4]

movecx,string;ecx->string

testecx,3;testifstringisalignedon32bits

jeshortmain_loop

第一句,esp+4這個就簡單了,在《【動態分配棧內存】之alloca內幕》一文中有詳細的解釋,這里只做簡單解釋,esp+4正是strlen參數的地址,這個地址屬于棧內存空間,再[esp+4]取值,則得到strlen參數指向的地址(strlen的參數為const char*)。假如代碼是這樣的:

[cpp]view plaincopy

charszName[]="masefee";

strlen(szName);

那么,上面的[esp+4]所得的地址值就是szName數組的首地址。前面的string equ [esp+4]并不會產生任何代碼,string只相當于是一個宏定義(至于為什么需要這個string,到后面就知道了,你要相信,這一切都是有理有據的,這也正是研究的樂趣之一),于是mov ecx,string就等價于mov ecx,[esp+4],這句是直接將參數指向的地址值賦值給ecx寄存器,ecx此刻就是字符串的首地址了。再下一句,test ecx,3,這句是測試ecx存放的這個地址值是不是4字節(32bits)對齊的,如果是,則跳轉到main_loop進行執行,否則,則繼續向下。我們先看未對齊的情況,自然就是緊接著的str_misaligned節:

[cpp]view plaincopy

str_misaligned:

moval,byteptr[ecx]

addecx,1

testal,al

jeshortbyte_3

testecx,3

jneshortstr_misaligned

addeax,dwordptr0;5bytenoptoalignlabelbelow

align16;shouldberedundant

先不看這段代碼,我們先推斷一下,前面說到了不對齊的情況,一般對于操作系統來說,對于內存的分配總是會對齊的,所以這里strlen一進來就檢查是否對齊,那么不對齊的情況是什么時候呢?如下:

[cpp]view plaincopy

charszName[]="masefee";

char*p=szName;

p++;//使p向后移動一個字節,本身假設以4字節對齊,移動之后就不再4字節對齊了

strlen(p);

當然,這里是我故意寫成這樣的,在實際中還有其他的情況,例如一個結構體里面有一個字符串,這個結構體是一字節對齊的,字符串的位置不確定時,那么字符串的首地址也就可能不是4字節對齊的。繼續前面的推斷,如果不對齊時,就會先讓其對齊,然后再繼續求長度,如果在讓其重新對齊的過程中,發現了結束符則停止,立刻返回長度。好了,推斷完畢。再看上面的匯編代碼,果然是這樣干的。

先是向ecx指向的內存里取一個字節到al里,然后ecx加1向后移動一個字節,再判斷al是否為0,如果為0則跳轉到byte_3節,否則繼續測試ecx當前的地址值是否已經對齊,未對齊則繼續取一個字節的值,再加ecx,直到對齊或者碰到結束符。當沒有碰到結束符且ecx存放的地址值已經對齊時,下面一句add eax,dword ptr 0,后面有注釋,表明這句代碼無實際意義。align 16和前面的add共同作用是為了將代碼以16字節對齊,后面的main_loop就是16字節對齊開始的地址了(又一次感受到了MS工程師們的聰明之處,考慮很周到)。

接下來該進入到main_loop了,很明顯這是主循環的意思,也是strlen的核心。這里用了很巧妙的算法,先分析前半部分代碼:

[cpp]view plaincopy

moveax,dwordptr[ecx];read4bytes

movedx,7efefeffh

addedx,eax

xoreax,-1

xoreax,edx

addecx,4

testeax,81010100h

jeshortmain_loop

首先,第一句向ecx所指向的內存里讀取了4個字節到eax中,很明顯是想4個字節處理一次。然后再看第二句,將edx賦值為0x7efefeff,這個數字看起來有什么規律,有什么用呢?來看看這個數字的二進制:

01111110 11111110 11111110 11111111 看看這個數字的二進制,我們注意到有4個紅色的0,他們都有一個特征,就是在每個字節的左邊,這有什么用?再聯想一下,在左邊,什么時候會被修改?很明顯,當右邊有進位時,會修改到這個0,或者這幾個0的位置與另外一個數相運算時會被改變。先不忙分析,先看下一句add edx,eax,這一句是將從ecx指向的內存里取出來的4字節整數與0x7efefeff相加,奇怪了,這樣相加有什么意義呢?仔細一想,驚訝了,原理這樣相加就能知道這個4字節整數中哪個或哪幾個字節為0了。為0則達到了strlen的目的,strlen就是為了找到結束符,然后返回長度。 再看這個加法的過程,加法的目的就是為了讓上面4個紅色的0中某些0被改變,如果有哪個0沒有改變并且最高位的0未改變,那說明這4個字節中存在某個或某些字節為0。這幾個紅色的0可以被稱為是洞(hole),而且也很形象。舉個例子:

byte3 byte2 byte1byte0

???????? 00000000 ???????? ???????? // eax

+ 01111110 11111110 11111110 11111111 // edx = 0x7efefeff 上面是假設兩個數相加,問號代表0或者1,但整個字節不全0,eax的byte2為全0,與edx的byte2相加,不管byte1和byte0怎么相加,最后進位都只能最多為1,那么byte3的最低位永遠不可能改變。以此類推,如果byte0為0,byte1的最低位永遠不可能改變,只有byte0有1位不為0,byte1的最低位都會收到進位,這也就是為什么edx的byte0為0xff了。所有byte都靠進位進行判斷,只要右邊沒有進位則必然存在byte為0。

繼續向下看,xor eax,-1則是將eax(從ecx指向的內存里取得的4字節)取反。然后xor eax,edx,這句的意圖是取出執行前面的加法之后的值(add edx,eax后edx的值)中未改變的那些位,繼續,add ecx,4則表示將ecx向后移動4個字節,方便下次進行運算。再之后,一句test eax,81010100h,這個0x81010100就是前面0x7efefeff取反,也就是幾個hole的位置為1。再與前面取出來的加法之后的值(add edx,eax后edx的值)中未改變的那些位相比較:如果結果為0,則表示加法之后的值(add edx,eax后edx的值)與原始值eax(取出來的原始字符串的4個字節)作比較,并且相對于0x7efefeff中的4個0(hold)的位置上,每一個0的位置(hole)都被改變了(或者相對于0x81010100中4個1(同樣是hold的位置)的位置上,每一個1的位置(hole)都被改變了);如果不為0,同理比較,則發現有字節為0。由此看來,與0x81010100進行test就是為了判斷從字符串取出來的4個字節與0x7efefeff相加之后的值的那幾個hold的位置相對于原始的4個字節中的那幾個hole的位置里,哪些hole位置的位是被改變了的。如果每個hole的位置都改變了則test結果為0,表示沒有字節為0,否則,則表示有字節為0。

當發現有字節為0時,則應該對取出來的4字節進行逐字節判斷哪個字節為0了,如下:

[cpp]view plaincopy

moveax,[ecx-4]

testal,al;isitbyte0

jeshortbyte_0

testah,ah;isitbyte1

jeshortbyte_1

testeax,00ff0000h;isitbyte2

jeshortbyte_2

testeax,0ff000000h;isitbyte3

jeshortbyte_3

jmpshortmain_loop;takenifbits24-30areclearandbit

;31isset

如上,第一句[ecx-4]的原因是因為ecx在前面加了4,因此要減4重新去開始的4字節,然后逐字節判斷哪個字節為0,代碼很簡單,這里就不詳細說明了。這里如果發現了某個字節為0,則跳轉到相應的尾部節中,如下:

[cpp]view plaincopy

byte_3:

leaeax,[ecx-1]

movecx,string

subeax,ecx

ret

byte_2:

leaeax,[ecx-2]

movecx,string

subeax,ecx

ret

byte_1:

leaeax,[ecx-3]

movecx,string

subeax,ecx

ret

byte_0:

leaeax,[ecx-4]

movecx,string

subeax,ecx

ret

以byte_3為例,也就是取出來的四個字節中,第4個字節為0,前3個字節不為0,于是eax就應該等于ecx-1,然后將ecx重新賦值為字符串的首地址(到這里你應該明白了為啥要有string這個宏了吧)。最后sub eax,ecx則直接獲得了字符串的長度。然后ret返回到上層。整個strlen就結束了。

通過前面的分析,我們已經知道了strlen的原理,并且更深刻領略了算法的美妙。我們可以將這個匯編版本的strlen翻譯成C語言版,如下:

[cpp]view plaincopy

size_tstrlen(constchar*str)

{

constchar*ptr=str;

for(;((int)ptr&0x03)!=0;++ptr)

{

if(*ptr=='\0')

returnptr-str;

}

unsignedint*ptr_d=(unsignedint*)ptr;

unsignedintmagic=0x7efefeff;

while(true)

{

unsignedintbits32=*ptr_d++;

if((((bits32+magic)^(bits32^-1))&~magic)!=0)//bits32^-1等價于~bits32

{

ptr=(constchar*)(ptr_d-1);

if(ptr[0]==0)

returnptr-str;

if(ptr[1]==0)

returnptr-str+1;

if(ptr[2]==0)

returnptr-str+2;

if(ptr[3]==0)

returnptr-str+3;

}

}

}

好了,strlen就差不多分析完了,最后面的C語言版本還可以變化,例如根據字符的編碼集,進行特殊化。不過一般是不需要的,通用一些更好。我做了一個測試,將本文開頭的C語言版本、最后的C語言版本以及crt的匯編版本的性能進行對比,求相同字符串的長度,求10000000次,開啟O2優化,三者平均耗時為:

普通C語言版本:723毫秒

后面的翻譯C版本:315毫秒

CRT匯編版本:218毫秒 可見,后兩者的性能有一定的提升,這里需要說明一點,crt的strlen函數屬于intrinsic函數,所謂intrinsic函數,可以稱作為內部函數,這與inline函數有點類似,但是不是inline之意。inline不是強制的,在編譯器編譯時也是有所區別的。intrinsic函數相當于是在編譯器在編譯時根據上下文等情況來確定是否將函數代碼進行匯編級內聯,在內聯的同時進行優化,由此既省去了函數調用開銷,同時優化也更直接明了。編譯器熟悉intrinsic函數的內在功能,很多時候又稱為內建函數,因此編譯器可以更好的整合及優化,目的只有一個,在特定的環境下,選擇最優的方案。就拿strlen來說,例如這樣一段代碼:

[cpp]view plaincopy

intmain(intargc,char**argv)

{

intlen=strlen(argv[0]);

printf("%d",len);

return0;

}

在debug下禁用優化、release下禁用優化或release下最小化大小(/O1)時,可以強制開啟intrinsic內部函數選項(/Oi),這樣開啟之后,上面的strlen函數將不再調用crt的匯編版本函數,而是直接內嵌到main函數代碼里,如下(debug或release下禁用優化并開啟內部函數(/Oi)):

[cpp]view plaincopy

intlen=strlen(argv[0]);

0042D8DEmoveax,dwordptr[argv]

0042D8E1movecx,dwordptr[eax]

0042D8E3movdwordptr[ebp-0D0h],ecx

0042D8E9movedx,dwordptr[ebp-0D0h]

0042D8EFaddedx,1

0042D8F2movdwordptr[ebp-0D4h],edx

0042D8F8moveax,dwordptr[ebp-0D0h]<------???

0042D8FEmovcl,byteptr[eax]|

0042D900movbyteptr[ebp-0D5h],cl|//逐字節計算

0042D906adddwordptr[ebp-0D0h],1|

0042D90Dcmpbyteptr[ebp-0D5h],0|

0042D914jnemain+38h(42D8F8h)//---------

0042D916movedx,dwordptr[ebp-0D0h]

0042D91Csubedx,dwordptr[ebp-0D4h]

0042D922movdwordptr[ebp-0DCh],edx

0042D928moveax,dwordptr[ebp-0DCh]

0042D92Emovdwordptr[len],eax

如果在release下開啟最小化大小(/O1)并開啟內部函數(/Oi)時,編譯后代碼如下:

[cpp]view plaincopy

intlen=strlen(argv[0]);

00401000moveax,dwordptr[esp+8]

00401004moveax,dwordptr[eax]

00401006leaedx,[eax+1]

00401009movcl,byteptr[eax]<------??

0040100Binceax|//逐字節計算

0040100Ctestcl,cl|

0040100Ejnemain+9(401009h)-------

00401010subeax,edx

代碼簡潔多了,同樣沒有函數調用開銷(其實,你會驚訝的發現,這幾句代碼正是本文開篇第二個C語言版的strlen的反匯編代碼,當然是經過優化后的代碼,這里省去了調用開銷。其實,本文前面開頭的兩個strlen,在開啟較高優化級別時,編譯器也會將這兩個函數進行優化內嵌,也就與intrinsic函數一致了。這說明一點,編譯器是人性化的,只要能夠滿足優化的條件,就會果斷進行優化)。在開啟最小化大小(/O1)優化并開啟內部函數(/Oi)優化與release下開啟最大化速度(/O2)或完全優化(/Ox)時,產生的代碼是一致的。與release下開啟最大化速度(/O2)或完全優化(/Ox)時,就算你不開啟內部函數(/Oi)優化,編譯器同樣會將strlen處理掉產生上面的代碼。這個跟優化的級別有關,級別高了,自然就會更全面的優化,不管你是否強制設置一些東西。也算是一個人性化設計吧。 要開啟某函數進行內部函數優化,可以通過代碼來開啟,如下:

[cpp]view plaincopy

#pragmaintrinsic(strlen)

有開啟,自然也有關閉,如下:

[cpp]view plaincopy

#pragmafunction(strlen)

強制將strlen的優化關閉,這樣就算你是最大化速度(/O2)或完全優化(/Ox),照樣會調用crt的strlen函數。這兩者的具體詳細說明,請查閱MSDN,或點擊這里。

關于這個intrinsic pragma,MSDN有詳細準確的解釋,還是英文原文更能體會其本意:

Theintrinsicpragma tells the compiler that a function has known behavior. The compiler may call the function and not replace the function call with inlineinstructions, if it will result in better performance. .........

Programs that use intrinsic functions are faster because they do not have the overhead of function calls but may be larger due to the additional code generated.

對了,不要試圖用這兩個東西來強制開啟或關閉一個普通函數的(/Oi)優化,所謂intrinsic,當然是編譯器內定的一些函數,也算是做了一些細節上優化的可選擇性吧。如果你不信我的,那你肯定會得到一個警告:

warning C4163: “xxxxx”: 不可用作內部函數.

對于intrinsic的相關優化,編譯器處理得比較靈活,這代表它并不是強制性的,如果開啟SSE,編譯器還會考慮SSE優化,在原理上,知道有這么回事就是了,本文的重點在于如何去挖掘和思考諸多細節。至于具體的內定的函數有哪些,以及有哪些詳細說明,請查閱MSDN,或者點擊前面的鏈接。這里就不再累述了,已經寫了這么長了。。

與此同時再一次感嘆MS的工程師們,細節做得很好。這也值得國內IT行業浮躁環境下的coder們深思。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7605

    瀏覽量

    136903
  • 字符串
    +關注

    關注

    1

    文章

    579

    瀏覽量

    20528
  • 函數
    +關注

    關注

    3

    文章

    4332

    瀏覽量

    62653
  • 代碼
    +關注

    關注

    30

    文章

    4790

    瀏覽量

    68649

原文標題:字符串函數strlen的深入研究

文章出處:【微信號:C_Expert,微信公眾號:C語言專家集中營】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    C語言字符串函數strcat|strcpy|strlen|strcmp的用法及原型

    strcat(str1,str2) 意為將字符串str2連接到字符串str1之后。
    發表于 11-24 10:10 ?847次閱讀

    字符串函數測試學習工程

    字符串函數測試學習工程
    發表于 07-01 16:38 ?6次下載

    Labview之字符串長度函數

    Labview之字符串長度函數,很好的Labview資料,快來下載學習吧。
    發表于 04-19 10:43 ?0次下載

    字符串的輸入輸出及相關函數

    字符串的輸入輸出及相關函數
    的頭像 發表于 09-14 11:52 ?6095次閱讀
    <b class='flag-5'>字符串</b>的輸入輸出及相關<b class='flag-5'>函數</b>

    PHP多字節字符串處理函數mbstring函數庫的詳細資料說明

    PHP內置的字符串長度函數strlen無法正確處理中文字符串,它得到的只是字符串所占的字節數。對于GB2312的中文編碼,
    發表于 02-20 14:30 ?9次下載
    PHP多字節<b class='flag-5'>字符串</b>處理<b class='flag-5'>函數</b>mbstring<b class='flag-5'>函數</b>庫的詳細資料說明

    C語言的字符串處理函數

    指針是神奇的,指向整型的指針int *p1,可以操作整型數組int a[];指向字符型的指針char *p2,可以操作字符數組(字符串)char str[];更靈活的是,在函數的傳遞中
    發表于 07-24 17:37 ?4次下載
    C語言的<b class='flag-5'>字符串</b>處理<b class='flag-5'>函數</b>

    LabVIEW的常用字符串操作教程免費下載

    字符串操作與信息的保存和顯示密不可分,而字符串操作運用也是LabⅥEW程序設計的一個難點,因此熟練使用字符串操作函數是使用LabⅥEW進行編程所必備的能力之
    發表于 08-21 14:51 ?26次下載
    LabVIEW的常用<b class='flag-5'>字符串</b>操作教程免費下載

    C語言編程字符串函數匯總資源下載

    C語言編程字符串函數匯總資源下載
    發表于 04-15 16:18 ?9次下載
    C語言編程<b class='flag-5'>字符串</b><b class='flag-5'>函數</b>匯總資源下載

    字符串函數重寫練習

    字符串函數重寫練習:字符串比較、字符串拼接、字符串查找、字符串拷貝、內存比較、內存拷貝、內存初始
    的頭像 發表于 05-05 15:02 ?1999次閱讀

    C語言總結_字符串函數封裝練習

    字符串函數重寫練習:字符串比較、字符串拼接、字符串查找、字符串拷貝、內存比較、內存拷貝、內存初始
    的頭像 發表于 08-14 09:42 ?1002次閱讀

    MySQL替換字符串函數REPLACE

    MySQL是目前非常流行的開源數據庫管理系統之一,它具有強大的功能和性能。其中之一的字符串函數REPLACE,可以用于替換字符串中的指定字符字符串
    的頭像 發表于 11-30 10:44 ?1559次閱讀

    oracle中拼接字符串函數

    在Oracle中,我們可以使用 CONCAT 函數來拼接字符串。CONCAT 函數接受兩個參數,它將這兩個參數連接起來并返回相應的字符串結果。 語法示例: CONCAT(string1
    的頭像 發表于 12-06 09:49 ?2942次閱讀

    strlen和sizeof的異同

    1,strlen函數作用:用于計算以空字符'\0'結尾的字符串的長度,即字符串中的
    的頭像 發表于 12-13 08:00 ?687次閱讀
    <b class='flag-5'>strlen</b>和sizeof的異同

    labview中常用的字符串函數有哪些?

    在LabVIEW中,常用的字符串函數廣泛覆蓋了對字符串的各種操作,包括但不限于格式化、搜索、替換、連接、計算長度等。以下是一些常用的字符串函數
    的頭像 發表于 09-04 15:43 ?745次閱讀

    labview字符串如何轉換為16進制字符串

    在LabVIEW中,將字符串轉換為16進制字符串是一個常見的需求,尤其是在處理數據通信和硬件接口時。LabVIEW提供了多種方法來實現這一轉換,包括使用內置函數、編寫VI(Virtual
    的頭像 發表于 09-04 15:54 ?2513次閱讀
    主站蜘蛛池模板: 入禽太深视频免费视频| 国产精品美女久久久久浪潮AV| 97视频在线观看免费播放| 国精产品一区一区三区有限公司| 日夜啪啪一区二区三区| av av在线| 欧美日韩一级黄色片| 99热最新网站| 女王黄金vk| av天堂网2017avtt| 伦理片在线线249| 91精品国产91热久久p| 免费观看美女的网站| 99国产精品免费视频| 欧美激情一区二区三区AA片| 99热这里有精品| 日本学生VIDEOVIDEOS更新| 大地影院免费观看视频| 日日噜噜大屁股熟妇| 公主纯肉高H文| 性一交一乱一色一视频| 好男人社区| 中文国产成人精品久久免费| 六度影院最新| 北条麻妃夫の友人196| 十分钟在线观看免费视频高清WWW| 国产精品JK白丝AV网站| 亚洲精品国产专区91在线| 精品性影院一区二区三区内射 | 国际老妇高清在线观看| 亚洲精品久久久无码AV片软件| 黄色小说男男| 777午夜精品久久AV蜜臀| 青青草原国产在线观看| 国产精自产拍久久久久久蜜| 亚洲欧洲日本天天堂在线观看| 久久伊人免费| 成人精品亚洲| 亚洲精品视频在线免费| 美女洗澡脱得一二干净| 敌伦小芳的第一次|