【问题标题】:W1024 Combining signed and unsigned types - widened both operandsW1024 组合有符号和无符号类型 - 加宽了两个操作数
【发布时间】:2015-04-03 10:16:10
【问题描述】:

如何防止出现此警告? [DCC 警告] uFvSystem.pas(293): W1024 结合有符号和无符号类型 - 加宽了两个操作数

function LinkerTimestamp: TDateTime; overload;
begin
  Result := PImageNtHeaders(HInstance + PImageDosHeader(HInstance)^._lfanew)
   ^.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta;
end;

【问题讨论】:

    标签: delphi


    【解决方案1】:

    错误消息表明您正在使用混合的有符号和无符号操作数执行整数运算。唯一的整数算术在这里:

    HInstance + PImageDosHeader(HInstance)^._lfanew
    

    第一个操作数是无符号的,第二个是有符号的,即使它必须是正数。

    您可以通过强制转换来抑制警告。最好在无符号上下文中执行算术,从而避免范围检查错误。因此,演员表被放置在第二个操作数周围:

    HInstance + NativeUInt(PImageDosHeader(HInstance)^._lfanew)
    

    HInstance + Cardinal(PImageDosHeader(HInstance)^._lfanew)
    

    如果您有没有NativeUInt 的旧版Delphi。

    但是,您实际上是在对指针执行算术运算,所以我会这样写:

    PByte(HInstance) + PImageDosHeader(HInstance)^._lfanew
    

    PAnsiChar(HInstance) + PImageDosHeader(HInstance)^._lfanew
    

    PByte 不支持算术的旧 Delphi 版本中。

    【讨论】:

      【解决方案2】:

      _lfanew 字段是LongIntHInstance 变量可能是THandle,它是Cardinal 或其他等效类型的别名。有您的签名和未签名类型。

      sum应该是什么类型的?可能值的范围比THandle 的大小宽一位。 (一个 m 位数和一个 n 位数之和最多需要max(m, n) 位。)所涉及的类型都不够大,因此编译器将它们都提升为更广泛的类型,以适应全系列。

      您对编译器不知道的这些变量的范围有所了解。特别是,您知道_lfanew 是一个以HInstance 为基础的内存范围的偏移量。只要没有文件损坏,HInstance_lfanew 的总和将是有效地址,因此您可以安全地将 _lfanew 类型转换为无符号类型,并确信总和不会溢出:

      Result := PImageNtHeaders(HInstance + UIntPtr(PImageDosHeader(HInstance)^._lfanew))
        ^.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta;
      

      如果您的 Delphi 版本提供,请使用 UIntPtr。否则,NativeUIntCardinal 可以。

      【讨论】:

      • 第二段并不能真正证明警告的合理性。即使两种类型相同,加法也可能溢出。我认为该警告实际上是因为编译器没有理由为表达式选择类型。表达式是 a + b。 a + b 应该是 a 的类型,还是 b 的类型?
      猜你喜欢
      • 1970-01-01
      • 2012-10-27
      • 2019-06-10
      • 2013-02-04
      • 2017-04-05
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-27
      相关资源
      最近更新 更多