Delphi 与空字符串相比,测试字符串长度生成的代码更多?

Delphi 与空字符串相比,测试字符串长度生成的代码更多?,delphi,Delphi,在Delphi中,string'生成的代码似乎少于Length(string)>0 比较在TMyClass.UpdateString(const strMyString:string)中定义的空字符串: 什么?字符串长度不应该是cmp dword ptr[ebp-$04],$00 我猜这是因为优化关闭了,编译器没有优化Lenght(归结为PInteger(PByte(s)-4)^),但我不明白为什么会有两种比较。事实上,即使启用了优化,这两种比较仍然存在: MyClassU.pas.27: if

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

比较在
TMyClass.UpdateString(const strMyString:string)
中定义的空字符串:

什么?字符串长度不应该是
cmp dword ptr[ebp-$04],$00

我猜这是因为优化关闭了,编译器没有优化
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
vs

MyClassU.pas.33:if(strMyString“”)那么
005CE6D9 85F6测试esi,esi
005CE6DB 740A jz$005ce6e7

第二块代码做更多的工作,毫不奇怪这需要更多的代码

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

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

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

至于为什么
Length
不能直接从字符串记录中读取,现在应该很明显了。空字符串作为nil指针实现,因此没有字符串记录。为了找到长度,您需要处理两种不同的情况:

  • 字符串为空,长度为0
  • 字符串不为空,从字符串记录中读取长度
    我想你已经回答了你自己的问题。这是假设问题确实是“测试字符串长度比比较空字符串生成更多的代码?”。FWIW必须有两个比较,空字符串没有任何长度指示符。因此,在访问它之前,您首先必须确定是否存在已分配的strec。
    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
    
    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
    
    MyClassU.pas.33: if (strMyString <> '') then
    005CE6D9 85F6             test esi,esi
    005CE6DB 740A             jz $005ce6e7