常数整数值的按位非运算符背后的逻辑是什么?
What is the logic behind the bitwise not operator on constant integer values?
这个问题听起来可能很傻,但我无法理解 not
常量整数运算符背后的想法。我得到以下结果:
not $FF
=> $FF00
not $FFFF
=> $FFFF0000
not $FFFFFFFF
=> [=17=]
not $FFFFFFFFFFFFFFFF
=> [=17=]
前两个值我觉得不对。
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.
这个问题听起来可能很傻,但我无法理解 not
常量整数运算符背后的想法。我得到以下结果:
not $FF
=>$FF00
not $FFFF
=>$FFFF0000
not $FFFFFFFF
=>[=17=]
not $FFFFFFFFFFFFFFFF
=>[=17=]
前两个值我觉得不对。
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.