使用Delphi中的十六进制内存值的常量单一

时间:2017-03-10 02:47:14

标签: delphi delphi-10-seattle

如何基于十六进制值创建单个常量,其中十六进制值是无符号整数,单位的原始内存。我想做这样的事情,但它不编译,这将尝试将十六进制值转换为单个,然后存储该转换的结果,而不是存储十六进制值本身:

LARGEST_SINGLE_LESS_THAN_ZERO = Single($80800000);

我收到“无效的Typecast”错误。

例如:

1的单个值在内存中存储为$ 3F800000。我希望能够创建const,让我使用$ 3F800000而不是1来设置值。

我还尝试了其他变种,例如没有运气:

LARGEST_SINGLE_LESS_THAN_ZERO = PSingle(@$80800000)^;

背景

我有一个方法,当我提供单个值时,我用它来获得下一个最小的单个:

type
  PInt32 = ^Int32;

function NextBefore(const aValue: Single): Single;
var
  int32Value: Int32;
begin
  // this function ignores special values nan/inf
  int32Value := PInt32(@aValue)^;
  if (UInt32(int32Value) = $80000000) or (int32Value = 0) then
  begin
    // special handling needed for -0 and 0. We need to go to the smallest
    // negative number.
    int32Value := $80800000;
  end
  else
  begin
    if int32Value >= 0 then
      Dec(int32Value)
    else
      Inc(int32Value);
  end;
  Result := PSingle(@int32Value)^;
end;

这非常有用,因为我们使用的矢量操作只能执行>或者<所以我们用它来做一个> =和一个< =的等价物。我们经常检查0.所以我们需要获取所有数据> = 0我们做这样的事情:

MyVector.ThresholdGT(NextBefore(0));

为其他开发人员提供这些类型操作的常量会更好。尝试使用下面的PSingle格式将无法正常工作,因为该数字不是变量。

2 个答案:

答案 0 :(得分:2)

为了使用十六进制值声明单个常量,使其不能被代码更改,可以分两步完成:

const 
  iLARGEST_SINGLE_LESS_THAN_ZERO : Int32 = $80800000; 
var 
  LARGEST_SINGLE_LESS_THAN_ZERO : Single absolute iLARGEST_SINGLE_LESS_THAN_ZERO;

尝试更改LARGEST_SINGLE_LESS_THAN_ZERO的值会产生编译错误:Left side cannot be assigned to

答案 1 :(得分:1)

由于语言的限制,很难干净地完成这项工作。也许您可以做的最好的事情是创建一个具有重叠的整数和单个字段的变体记录类型。

type
  TSingleIntegerVariantRec = record
    case Integer of
      0: (I: Integer);
      1: (S: Single);
  end;

一旦有了这种类型,就可以使用整数字段声明类型常量,然后读取单个字段。

const
  LARGEST_SINGLE_LESS_THAN_ZERO: TSingleIntegerVariantRec = (I: $80800000);
.... 
MyVector.ThresholdGT(LARGEST_SINGLE_LESS_THAN_ZERO.S);

如果你想添加一个额外的细微差别,你可以实现Single的隐式强制转换操作符,这样你就可以省略.S。如果您使该运算符内联,那么我怀疑发出的代码将非常有效。

这就是你要求的,但我不会声称它非常优雅。我是您,我会移动代码以使用下一个值进入库函数,以便您可以传递0并屏蔽库的使用者这些实现细节。

换句话说,您将添加一个ThresholdGTequal方法,其实现如下:

procedure TMyVector.ThresholdGTequal(const Value: Single);
begin
  ThresholdGT(NextBefore(Value));
end;

然后这段代码的消费者只写:

MyVector.ThresholdGTequal(0);

并且仍然没有注意到所有粗糙的实现细节。