对于常量整数值,按位运算符背后的逻辑是什么?

时间:2018-04-25 21:34:03

标签: delphi integer delphi-10.2-tokyo constant-expression

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

  • not $FF => $FF00
  • not $FFFF => $FFFF0000
  • not $FFFFFFFF => $00
  • not $FFFFFFFFFFFFFFFF => $00

前两个值对我来说是错误的。

documentation州:

  

例如,不对整数操作数

执行按位求反

以后:

  

not操作的结果与操作数

的类型相同

这与观察到的行为不一致。

完整代码示例:

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.

1 个答案:

答案 0 :(得分:4)

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

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

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

为避免过度混淆,因为您只提供签名的打印输出备选方案:

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

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

来自Declared_Constants#True_Constants

  

声明真常量的语法是:

const identifier = constantExpression
     

其中identifier是任何有效的标识符,而constantExpression是编译器可以在不执行程序的情况下评估的表达式。

     

如果constantExpression返回一个序数值,您可以使用值类型转换指定声明的常量的类型。

添加了完整的测试:

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.