Какова логика побитового оператора not для постоянных целочисленных значений? - PullRequest
0 голосов
/ 26 апреля 2018

Этот вопрос может показаться глупым, но я не могу понять идею, стоящую за оператором not для постоянных целых чисел.Я получаю следующие результаты:

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

Первые два значения мне кажутся неправильными.

Документация гласит:

Например, not выполняет побитовое отрицание целочисленного операнда

и более поздних версий:

Результат операции 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 голосов
/ 26 апреля 2018

Компилятор может * выбрать подходящий тип для истинных констант, если возможна неоднозначность.

Вам нужно помочь в этом случае, используя значение typecast:

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

, где идентификатором является любой действительный идентификатора constantExpression - это выражение, которое компилятор может вычислять без выполнения вашей программы.

Если constantExpression возвращает порядковое значение, вы можете указать тип объявленной константы, используя значение 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 $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.
...