如何在 C# 中将 byte[] 分配为指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/693710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to assign byte[] as a pointer in C#
提问by Ivan Prodanov
I have a function that generates a CRC check byte based on the content of any packet.The problem is in translating the function from C++ to C#
我有一个函数可以根据任何数据包的内容生成一个 CRC 校验字节。问题在于将函数从 C++ 转换为 C#
C++ code:
C++代码:
unsigned char GenerateCheckByte( char* packet, int length, unsigned long seed )
{
if( !packet ) return 0;
unsigned long checksum = 0xFFFFFFFF;
length &= 0x7FFF;
char* ptr = packet;
unsigned long moddedseed = seed << 8;
for( int i = 0; i < length; i++ )
checksum = ( checksum >> 8 ) ^ table[moddedseed + ( ( *(ptr++) ^ checksum ) & 0xFF )];
unsigned char result = ( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF );
return result;
}
the char*(packet) can also be defined as LPBYTE,the idea is that the value assigned to *packet is assigned to *ptr and as you see *ptr increases.Meaning a byte array is passed in and by increasing the value of the pointer it goes to the next byte.
char*(packet) 也可以定义为 LPBYTE,这个想法是将分配给 *packet 的值分配给 *ptr 并且如您所见 *ptr 增加。意思是传入一个字节数组并通过增加指向下一个字节的指针。
I tried to do it in C# and failed many times.After some hard work I figured out some code,but i can't execute it :?
我试图用 C# 来做,但失败了很多次。经过一番努力,我想出了一些代码,但我无法执行它:?
C# code
C# 代码
public static unsafe byte GenerateCheckByte(byte *packet, int length, UInt32 seed )
{
if (*packet == 0)
return 0;
UInt32 checksum = 0xFFFFFFFF;
length &= 0x7FFF;
byte *ptr = packet;
UInt32 moddedseed = seed << 8;
for (int i = 0; i < length; i++)
checksum = ( checksum >> 8 ) ^ Table.table[moddedseed + ( ( *(ptr++) ^ checksum ) & 0xFF )];
byte result = (byte)(( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF ));
return result;
}
It doesn't look that bad,but I can't call it
看起来没那么糟糕,但我不能称之为
unsafe
{
packetBuffer[5] = Functions.GenerateCheckByte(&packetBuffer[0], 18, packet.seedCRC);
}
error: "You can only take the address of an unfixed expression inside of a fixed statement initializer"
错误:“您只能在固定语句初始值设定项中获取未固定表达式的地址”
Please note
请注意
packetbuffer in both C++ and C# application is byte[] packetBuffer = new byte[18];
C++ 和 C# 应用程序中的 packetbuffer 都是 byte[] packetBuffer = new byte[18];
采纳答案by Daniel Earwicker
You could make the method accept a byte array:
您可以使该方法接受一个字节数组:
public static unsafe byte GenerateCheckByte(byte[] packetArray, int length, UInt32 seed)
{
fixed(byte *packet = packetArray)
{
... etc
}
}
It's better to keep the unsafe stuff hidden away as much as possible behind managed interfaces.
最好将不安全的东西尽可能多地隐藏在托管接口后面。
Then calling it would be easy:
然后调用它会很容易:
packetBuffer[5] = Functions.GenerateCheckByte(packetBuffer, 18, ...
In fact, it would be better to write GenerateCheckByte
to operate on an array anyway, instead of delving into unsafe
techniques:
事实上,GenerateCheckByte
无论如何编写对数组进行操作会更好,而不是钻研unsafe
技术:
public static unsafe byte GenerateCheckByte(byte[] packet, int length, UInt32 seed )
{
if (packet == null)
throw new ArgumentNullException("packet"); // the right way in C#
UInt32 checksum = 0xFFFFFFFF;
length &= 0x7FFF;
UInt32 moddedseed = seed << 8;
for (int i = 0; i < length; i++)
checksum = ( checksum >> 8 ) ^ Table.table[moddedseed + ( ( packet[i] ^ checksum ) & 0xFF )];
byte result = (byte)(( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF ));
return result;
}
Write the simplest, safest implementation you can, and only mess with pointers if you find a bottleneck in profiling.
尽可能编写最简单、最安全的实现,并且只有在发现分析瓶颈时才使用指针。
Are you just translating a lot of existing C/C++ into C#? There's little point doing that unless you get some new safety/maintainability from it. :)
您是否只是将大量现有的 C/C++ 翻译成 C#?除非您从中获得一些新的安全性/可维护性,否则这样做毫无意义。:)
回答by Phil Price
You need to 'pin' the byte array into memory to use it as a byte*.
您需要将字节数组“固定”到内存中以将其用作字节*。
byte checksum;
fixed(byte* pPacketBuffer = packetBuffer)
{
checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC)
}
packetBuffer[5] = checksum
References:
参考:
回答by Guffa
You shouldn't have to use unsafe code at all. If you send in a byte array to the function, it can access it without using pointers.
您根本不必使用不安全的代码。如果您向函数发送一个字节数组,它可以在不使用指针的情况下访问它。
I haven't tested the code, but it should be something like this:
我还没有测试过代码,但它应该是这样的:
byte GenerateCheckByte(byte[] packet, ulong seed) {
if (packet == null) return 0;
int length = packet.Length & 0x7FFF;
ulong checksum = 0xFFFFFFFF;
ulong moddedseed = seed << 8;
for (int i = 0; i < length; i++) {
checksum = (checksum >> 8) ^ table[moddedseed + ((packet[i] ^ checksum) & 0xFF)];
}
return (byte)(
((checksum >> 24) & 0xFF) +
((checksum >> 16) & 0xFF) +
((checksum >> 8) & 0xFF) +
(checksum & 0xFF)
);
}