读取和写入64位int中的各个位。

时间:2014-03-18 16:26:48

标签: delphi bit-shift

我必须在一个变量中存储多达7个字节的数据,并且能够读取和写入各个位。有4个字节,这是小菜一碟,我只是使用for循环并执行一次移位来写入该位或读取它:

data : int64;

data := $01 + ($00 shl 8 ) + ($00 shl 16 ) + ($FF shl 24);

for i := 31 downto 0 do
     begin
          if ((data shr i) and 1) = 1 then ShowMessage('data bit was one')
          else ShowMessage('data Bit was Zero');

end;

以正确的顺序读出位。

但是,当我尝试使用此方法超过32位时,似乎已经失败了:

data : int64;

data := $01 + ($00 shl 8 ) + ($00 shl 16 ) + ($00 shl 24) + ($FF shl 32);

for i := 39 downto 0 do
     begin
          if ((data shr i) and 1) = 1 then ShowMessage('data bit was one')
          else ShowMessage('data Bit was Zero');

end;

这不会以正确的顺序输出这些位,$ FF似乎被推到了堆栈的后面。它似乎读取位31到0然后读取位39到32.我如何克服这个问题?

3 个答案:

答案 0 :(得分:7)

您的常量被视为Int32值,并且计算使用32位值,并且在所有计算之后都会转换为Int64。 SHL执行为
{Value shl (Shift mod DATASIZE)},其中DATASIZE为32,因此对于32位类型,{shl 32}相当于{shl 0}。比较

  i64 := Int64($FF) shl 32;
and
  i64 := $FF shl 32;

(对于32位编译器,至少)

只需将常量强制转换为Int64以帮助编译器。

答案 1 :(得分:4)

你真的使用Int64表示吗?否则,如果您只是为了这些位,您可以简单地声明一个正确的类型并使用通常的set语法。您也可以使用Include / Exclude设置/重置单个位。

type
  T64BitSet = set of 0..63;

var
  data: T64BitSet;

begin
  data := [0, 32..39];  // set Bits

  for i := 39 downto 0 do
    begin
      if i in data then
        <data bit was one>
      else
        <data Bit was Zero>;
  end;
end;

答案 2 :(得分:4)

按位移位运算符的documentation表示(我强调):

  

操作x shl y和x shr y将x的值向左或向右移位y位,其中(如果x是无符号整数)相当于将x乘以或除以2 ^ y;结果与x的类型相同。例如,如果N存储值01101(十进制13),则N shl 1返回11010(十进制26)。 请注意,y的值以x 类型的大小为基础进行解释。因此,例如,如果x是整数,则x shl 40被解释为x shl 8,因为整数是32位而40 mod 32是8.

这解释了治疗:

$FF shl 32

文字$FF是32位整数,此表达式与$FF shl 0相同,即$FF

你需要左手操作数为64位类型,这是通过强制转换实现的:

UInt64($FF) shl 32