常数整数值的按位非运算符背后的逻辑是什么?

What is the logic behind the bitwise not operator on constant integer values?

这个问题听起来可能很傻,但我无法理解 not 常量整数运算符背后的想法。我得到以下结果:

前两个值我觉得不对。

documentation 状态:

For example, not performs bitwise negation on an integer operand

及以后:

The result of a not operation is of the same type as the operand

这与观察到的行为不符。

完整代码示例:

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; // = [=10=]
  uint64Value = not $FFFFFFFFFFFFFFFF; // = [=10=]
begin
  Invert(byteValue);
  Invert(wordValue);
  Invert(cardValue);
  Invert(uint64Value);
end;

end.

如果可能存在歧义,编译器可以自由*为真正的常量选择合适的类型。

在这种情况下,您需要使用值类型转换来提供帮助:

const
   byteValue = Byte(not $FF);  // => [=10=]  (ShortInt)
   wordValue = Word(not $FFFF); // => [=10=] (ShortInt) 

为避免过度混淆,因为您只提供签名的打印输出替代品:

const
   byteValue = ShortInt(not $FF);  // => [=11=] (ShortInt)
   wordValue = SmallInt(not $FFFF); // => [=11=]00 (SmallInt) 

当没有直接重载过程匹配序数类型时,很难预测编译器选择哪个重载。


来自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.


  • 免费,意味着它遵循某些未记录的规则。请参阅戴维斯的回答:

添加了完整测试:

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 [=13=]
  wordValue = SmallInt(not $FFFF); // = SmallInt [=13=]00
  cardValue = Integer(not $FFFFFFFF); // = Integer [=13=]000000
  uint64Value = Int64(not $FFFFFFFFFFFFFFFF); // = Int64 [=13=]00000000000000
begin
  Invert(byteValue);
  Invert(wordValue);
  Invert(cardValue);
  Invert(uint64Value);
end;

begin
  c;
  ReadLn;
end.