This question may sound silly but I can not understand the idea behind the not
operator on constant integers. I get the following results:
not $FF
=> $FF00
not $FFFF
=> $FFFF0000
not $FFFFFFFF
=> $00
not $FFFFFFFFFFFFFFFF
=> $00
The first two values look wrong to me.
The documentation states:
For example, not performs bitwise negation on an integer operand
and later:
The result of a not operation is of the same type as the operand
This is not in line with the observed behaviour.
Full code example:
unit Unit5;
interface
procedure c();
implementation
uses Vcl.Dialogs, System.SysUtils;
procedure Invert(v: ShortInt); overload; begin
ShowMessage('ShortInt $' + v.ToHexString());
end;
procedure Invert(v: SmallInt); overload; begin
ShowMessage('SmallInt $' + v.ToHexString());
end;
procedure Invert(v: Integer); overload;
begin
ShowMessage('Integer $' + v.ToHexString());
end;
procedure c();
const
byteValue = not $FF; // = $FF00
wordValue = not $FFFF; // = $FFFF0000
cardValue = not $FFFFFFFF; // = $00
uint64Value = not $FFFFFFFFFFFFFFFF; // = $00
begin
Invert(byteValue);
Invert(wordValue);
Invert(cardValue);
Invert(uint64Value);
end;
end.
The compiler is free* to pick a suitable type for true constants, if there can be an ambiguity.
You need to help out in this case by using a value typecast:
const
byteValue = Byte(not $FF); // => $00 (ShortInt)
wordValue = Word(not $FFFF); // => $00 (ShortInt)
To avoid overloaded confusion, since you only offer signed printout alternatives:
const
byteValue = ShortInt(not $FF); // => $00 (ShortInt)
wordValue = SmallInt(not $FFFF); // => $0000 (SmallInt)
When no direct overloaded procedure matches an ordinal type, it can be difficult to predict which overload the compiler selects.
From Declared_Constants#True_Constants:
The syntax for declaring a true constant is:
const identifier = constantExpression
where identifier is any valid identifier and constantExpression is an expression that the compiler can evaluate without executing your program.
If constantExpression returns an ordinal value, you can specify the type of the declared constant using a value typecast.
Added a full test:
program Project110;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
procedure Invert(v: ShortInt); overload; begin
WriteLn('ShortInt $' + v.ToHexString());
end;
procedure Invert(v: SmallInt); overload; begin
WriteLn('SmallInt $' + v.ToHexString());
end;
procedure Invert(v: Integer); overload;
begin
WriteLn('Integer $' + v.ToHexString());
end;
procedure Invert(v: Int64); overload;
begin
WriteLn('Int64 $' + v.ToHexString());
end;
procedure c();
const
byteValue = ShortInt(not $FF); // = ShortInt $00
wordValue = SmallInt(not $FFFF); // = SmallInt $0000
cardValue = Integer(not $FFFFFFFF); // = Integer $00000000
uint64Value = Int64(not $FFFFFFFFFFFFFFFF); // = Int64 $0000000000000000
begin
Invert(byteValue);
Invert(wordValue);
Invert(cardValue);
Invert(uint64Value);
end;
begin
c;
ReadLn;
end.