Fabio Vitale
Fabio Vitale

Reputation: 2287

W1024 Combining signed and unsigned types - widened both operands

How can I prevent this warning? [DCC Warning] uFvSystem.pas(293): W1024 Combining signed and unsigned types - widened both operands

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

Upvotes: 2

Views: 2891

Answers (2)

David Heffernan
David Heffernan

Reputation: 613222

The error message indicates that you are performing integer arithmetic with mixed signed and unsigned operands. The only integer arithmetic is here:

HInstance + PImageDosHeader(HInstance)^._lfanew

The first operand is unsigned, the second is signed, even though it must be positive.

You can suppress the warning with a cast. It is better to perform the arithmetic in an unsigned context and so avoid range check errors. Hence the cast is placed around the second operand:

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

or

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

if you have an older Delphi that does not have NativeUInt.

However, you are actually performing arithmetic on pointers and so I would write it like this:

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

or

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

in older Delphi versions for which PByte does not support arithmetic.

Upvotes: 5

Rob Kennedy
Rob Kennedy

Reputation: 163317

The _lfanew field is a LongInt. The HInstance variable is probably a THandle, which is an alias for Cardinal or some equivalent type. There are your signed and unsigned types.

What type should the sum have? The range of possible values is one bit wider than the size of THandle. (The sum of an m-bit number and an n-bit number needs at most max(m, n) bits.) Neither of the types involved is big enough, so the compiler promotes them both to a wider type that will accommodate the full range.

You know something about the ranges of these variables that the compiler doesn't. In particular, you know that _lfanew is an offset into a range of memory that has HInstance as its base. As long as there's no file corruption, the sum of HInstance and _lfanew will be a valid address, so you can safely type-cast _lfanew to an unsigned type with the confidence that the sum won't overflow:

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

Use UIntPtr if your version of Delphi offers it. Otherwise, NativeUInt or Cardinal will do.

Upvotes: 0

Related Questions