关于位操作的问题?(高难度)(100分)

Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
不用把0去掉,而且也没法去,机器怎么表示小于一个字节的数据类型呢?
如果“要将提取出的转化为常见的数据类型如 Integer”(要注意integer是有符号的),
你可以用类似下面的方法将4个字节转换成一个DWORD(和integer一样也是4个字节,但
无符号):

function BTDW(b: array of BYTE):DWORD;
var dw,tdw: DWORD;
begin
// b[0]*(2^24)+b[1]*(2^16)+b[2]*(2^8)+b[3]

dw:=0;
tdw:=0;
tdw:=b[0]
dw:= dw+(tdw shl 24);
tdw:=b[1]
dw:=dw+(tdw shl 16);
tdw:=b[2]
dw:=dw+(tdw shl 8);
dw:=dw+b[3];
result := dw;
end;
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
可是不一定正好是四个字节的呀,右边的不管也算,再怎么也得把左面的去掉才以转换呀
 
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
$0F(00001111)和$F(1111)有区别吗?

告诉我,你的array of byte有多长,你想转换成什么数据类型,具体些。
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
长度变化,而且提取的起始和结束位置也是变化的,难就难在不一定正好从字节的边界处
提取
比如你的程序提取后的数据是:00011010,可是我要的却是1101
 
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
将00011010右移一位(shr 1)即可得到你要的数据,也就是通过将右边的0移位可以实现
你的要求,左边的0是不影响大小的。
 
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
问题是你要转换成什么?如果就转换成一个integer,那不能超过4个字节,否则integer不能
表示。
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
可是我得到是大于一字节的数据,难道能对整个buf右移吗
 
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
你可以先转换,再除以2的n次方,前提是你只有4个字节(假设你要转换成integer),如果
你有5个字节,你无法转换成integer的。
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
我要的在4字节以内,但是这4字节不是正好从字节的边界算起
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
我的qq:9422794
到QQ上聊好不好
 
J

jsxjd

Unregistered / Unconfirmed
GUEST, unregistred user!
问题是如果你取一段很长的(比如1000 bit)的二进制,
没有合适的数据类型表示,而且它的前几位很可能是0.
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
不超过64位的,大概5-6字节
 
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
任意n个字节移位:

function GetRightZeroNum(b: byte):integer;
var i: integer;
begin
for i:= 7 downto 0 do
begin
result := b and ($FF shr i);
if result <> 0 then
begin
result := 7-i;
break;
end;
end;
end;

procedure ConvertData(var data: array of byte);
var
len, i: integer;
LastByte, B1, B2: byte;
ident: integer;
begin
len := length(data);
LastByte := data[len-1];
ident := GetRightZeroNum(LastByte);
B1 := $FF shr ident;
B2 := B1;
for i := (len-1) downto 0 do
begin
if i<>0 then B2 := (data[i-1] and B1)shl (8-ident)
else B2 := 0;
data := (data shr ident)or B2;
end;
end;

运行该过程前,应确保最后一个字节不是全0,若是可做一个简单的转换,将最后全0的字节
去掉。
 
J

jsxjd

Unregistered / Unconfirmed
GUEST, unregistred user!
这么小的量,没有密集调用,效率不会有问题。
用其它类型返回,前导0不好处理。
 
D

D_LOVER

Unregistered / Unconfirmed
GUEST, unregistred user!
我把问题具体化吧:
这是SWF文件的文件头的格式,其中的"UI"指的是无符号整数
Signature UI8 Signature byte always 'F'
Signature UI8 Signature byte always 'W'
Signature UI8 Signature byte always 'S'
Version UI8 Single byte file version (e.g. 0x04 for SWF 4)
FileLength UI32 Length of entire file in bytes
FrameSize RECT Frame size in twips
FrameRate UI16 Frame delay in 8.8 fixed number of frames per second
FrameCount UI16 Total number of frames in movie

其中有个结构RECT也就存放FrameSize的,它的结构是这样的
RECT
Field Type Comment
Nbits nBits = UB[5] Bits used for each subsequent field
Xmin SB[nBits] X minimum position for rectangle in twips
Xmax SB[nBits] X maximum position for rectangle in twips
Ymin SB[nBits] Y minimum position for rectangle in twips
Ymax SB[nBits] Y maximum position for rectangle in twips

在这个结构的头一个字节的前5位放NBits的值,NBits的值决定了后续的Xmin,Xmax,Ymin
Ymax每个用多少位表示

我要得到Xmin,Xmax,Ymin,Ymax的值,麻烦就麻烦在Xmin从头一个字节的后三位开始的,
也就是不是用整字节存放的



 

Similar threads

顶部