我正在将一个库从C ++移植到C#,但遇到了一个我不确定如何解决的场景,这涉及将unsigned char *
转换为unsigned int *
。
C ++
unsigned int c4;
unsigned int c2;
unsigned int h4;
int pos(unsigned char *p)
{
c4 = *(reinterpret_cast<unsigned int *>(p - 4));
c2 = *(reinterpret_cast<unsigned short *>(p - 2));
h4 = ((c4 >> 11) ^ c4) & (N4 - 1);
if ((tab4[h4][0] != 0) && (tab4[h4][1] == c4))
{
c = 256;
return (tab4[h4][0]);
}
c = 257;
return (tab2[c2]);
}
C#(这是错的):
public uint pos(byte p)
{
c4 = (uint)(p - 4);
c2 = (ushort)(p - 2);
h4 = ((c4 >> 11) ^ c4) & (1 << 20 - 1);
if ((tab4[h4, 0] != 0) && (tab4[h4, 1] == c4)) {
c = 256;
return (tab4[h4, 0]);
}
c = 257;
return (tab2[c2]);
}
我相信在C#示例中,您可以将byte p
更改为byte[]
,但是如果将byte[]
转换为单个uint值,我将毫无头绪。
此外,有人可以向我解释一下,为什么要将unsigned char *
投放到unsigned int *
?它的目的是什么?
任何帮助/推动方向都非常有用。
答案 0 :(得分:3)
有问题的行的翻译将是:
int pos(byte[] a, int offset)
{
// Read the four bytes immediately preceding offset
c4 = BitConverter.ToUInt32(a, offset - 4);
// Read the two bytes immediately preceding offset
c2 = BitConverter.ToUInt16(a, offset - 2);
并将来自x = pos(&buf[i])
的调用(即使在C ++中与x = pos(buf + i)
相同)更改为
x = pos(buf, i);
一个重要的注意事项是现有的C ++代码是错误的,因为它违反了严格的别名规则。
答案 1 :(得分:1)
在C#中实现类似功能不需要涉及在逐个语句的基础上复制C版本的代码,特别是当原始代码使用指针时。
当我们假设int
为32位的架构时,您可以像这样简化C#版本:
uint[] tab2;
uint[,] tab4;
ushort c;
public uint pos(uint c4)
{
var h4 = ((c4 >> 11) ^ c4) & (1 << 20 - 1);
if ((tab4[h4, 0] != 0) && (tab4[h4, 1] == c4))
{
c = 256;
return (tab4[h4, 0]);
}
else
{
c = 257;
var c2 = (c4 >> 16) & 0xffff; // HIWORD
return (tab2[c2]);
}
}
这种简化是可能的,因为c4和c2重叠:c2是c4的高位字,仅在tab4
中的查找不匹配时才需要。
(标识符N4
出现在原始代码中,但在您自己的翻译中被表达式1&lt;&lt; 20替换。
调用代码必须循环遍历int数组,根据注释是可能的。虽然原始C ++代码从偏移量4开始并回顾过去,但C#等价物将从偏移0开始,这似乎是更自然的事情。
答案 2 :(得分:0)
在C ++代码中,您发送指向char的指针,但通常C#不使用这种方式处理内存,您需要数组而不是指针。
但您可以使用unsafe
关键字直接处理内存。
https://msdn.microsoft.com/en-us/library/chfa2zb8.aspx