测试字符串长度会产生比空字符串更多的代码吗?

afa*_*rah 4 delphi

在Delphi中,string <> ''似乎生成的代码少于Length(string) > 0.

比较空字符串,定义TMyClass.UpdateString(const strMyString : String)如下:

MyClassU.pas.31: begin
005CE6A0 55               push ebp                           
005CE6A1 8BEC             mov ebp,esp
005CE6A3 83C4F8           add esp,-$08
005CE6A6 8955F8           mov [ebp-$08],edx
005CE6A9 8945FC           mov [ebp-$04],eax
MyClassU.pas.32: if (strMyString <> '') then
005CE6AC 837DF800         cmp dword ptr [ebp-$08],$00
005CE6B0 740E             jz $005ce6c0
Run Code Online (Sandbox Code Playgroud)

据我了解,这是将动态分配的字符串([ebp-$08])的地址与零进行比较.有道理,因为空字符串指向nil.

比较长度,定义TMyClass.UpdateString2(const strMyString : String)如下:

MyClassU.pas.25: begin
005CE664 55               push ebp
005CE665 8BEC             mov ebp,esp
005CE667 83C4F4           add esp,-$0c
005CE66A 8955F8           mov [ebp-$08],edx
005CE66D 8945FC           mov [ebp-$04],eax
005CE670 8B45F8           mov eax,[ebp-$08]
MyClassU.pas.26: if (Length(strMyString) > 0) then
005CE673 8945F4           mov [ebp-$0c],eax
005CE676 837DF400         cmp dword ptr [ebp-$0c],$00
005CE67A 740B             jz $005ce687
005CE67C 8B45F4           mov eax,[ebp-$0c]
005CE67F 83E804           sub eax,$04
005CE682 8B00             mov eax,[eax]
005CE684 8945F4           mov [ebp-$0c],eax
005CE687 837DF400         cmp dword ptr [ebp-$0c],$00
005CE68B 7E0E             jle $005ce69b
Run Code Online (Sandbox Code Playgroud)

什么?不应该只是cmp dword ptr [ebp-$04],$00,因为字符串长度存储在字符串中的偏移量 - $ 04内吗?

我的猜测是因为优化已关闭且编译器没有优化Lenght(归结为PInteger(PByte(S) - 4)^),但我不明白为什么有两个比较.事实上,即使启用了优化,两种比较都会出现:

MyClassU.pas.27: if (Length(strMyString) > 0) then
005CE6B1 8BC6             mov eax,esi
005CE6B3 85C0             test eax,eax
005CE6B5 7405             jz $005ce6bc
005CE6B7 83E804           sub eax,$04
005CE6BA 8B00             mov eax,[eax]
005CE6BC 85C0             test eax,eax
005CE6BE 7E0A             jle $005ce6ca
Run Code Online (Sandbox Code Playgroud)

VS

MyClassU.pas.33: if (strMyString <> '') then
005CE6D9 85F6             test esi,esi
005CE6DB 740A             jz $005ce6e7
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 11

第二个代码块做了更多的工作,并且毫不奇怪,需要更多的代码.

在第一个代码块中,您只需与空字符串进行比较.编译器知道这相当于将指针与nil进行比较并生成该代码.

第二个代码块首先获得字符串的长度.这涉及检查指针是否为零.如果是,则长度为零.否则,从字符串元数据记录中读取长度.

编译器根本不知道每次指针不是nil时,长度必须为正,因此无法优化.

至于为什么Length不直接读取字符串记录,现在应该是显而易见的.空字符串实现为nil指针,因此没有字符串记录.为了找到处理两种不同情况所需的长度:

  1. 字符串为空,长度为0.
  2. 字符串不为空,从字符串记录中读取长度.