C# * 和 & 运算符用于指向数组

Posted

技术标签:

【中文标题】C# * 和 & 运算符用于指向数组【英文标题】:C# * and & operaor for pointing to array 【发布时间】:2019-06-23 19:42:35 【问题描述】:

我正在将 C++ CRC 函数转换为 C#,但在函数参数中传递指向 (unsigned char) 字节数组的指针时遇到问题。在下面的 C++ 示例中

unsigned int CRC16_Calculation(unsigned char *buf, unsigned int len)
  unsigned int ix;
  unsigned int index;
  unsigned int crc = 0;

  for(ix=0; ix<len; ix++)
  
    index = (high ^ buf[ix]) & 0x00FF;  
    crc = (low * 256) ^ Crc16Tbl[index];
  
  return crc;

我能够将这个函数翻译成 C#。

    public static unsafe ushort ComputeChecksum(byte[] buffer, ushort len)

    ushort index;
    ushort crc = 0;
    for (int i = 0; i < len; ++i)
    
        index = (ushort)((low ^ buffer[i]) & 0x00FF);
        crc = (ushort)((high * 256) ^ table[index]);
    

    return crc;

我需要使用C++中的函数如下:

crc= CRC16_Calculation(&Array[3], sizeof(Array)-3);

但是在 C# 中给我一个编译器错误。

ushort crc = ComputeChecksum(Array[3], (ushort)(Array.Length-3));

参数 1:无法从 'byte[]*' 转换为 'byte[]'。

'Program.ComputeChecksum(byte[], ushort)' 的最佳重载方法匹配有一些无效参数

问题是 C++ 函数使用对 unsigned char 数组的指针,而这在 C# 中是不可能的,仅在使用不安全时才对应?

【问题讨论】:

您说“我需要在 C++ 中按如下方式使用该函数......但在 C# 中它给了我”。问题是如何将 call 转换为函数?你能给我们看一个最小的调用示例吗? 它一定是不安全的吗?如果不是:不要“翻译”。写下它的作用,然后用“C#方式”实现它。像这样的翻译几乎不会导致合理的代码(根据我的经验)。 您可能会发现最简单的解决方案是在 C# 中添加一个额外的 ushort offset 参数,并在距数组开头的那个偏移量处启动 CRC。 我添加了给出错误的 C# 函数调用。这仅在使用 Array[3] 时发生。添加数组将起作用。 【参考方案1】:

首先在 C# 中,只将数组传递给没有长度的方法就足够了,因为 Array 类包含 Length 属性。所以你可以重写你的方法来跟随(unsafe 不是必需的,因为你没有在 C# 代码中使用指针)

public static ushort ComputeChecksum(byte[] buffer)

    ushort index;
    ushort crc = 0;
    for (int i = 0; i < buffer.Length; ++i) //using Length property
    
        index = (ushort)((low ^ buffer[i]) & 0x00FF);
        crc = (ushort)((high * 256) ^ table[index]);
    

    return crc;

您的问题几乎没有解决方案。第一个是使用Linq。你可以这样调用你的方法

ushort crc = ComputeChecksum(arr.Skip(3).ToArray());

要使用Skip 方法,您需要添加using System.Linq;

第二种解决方案是使用Span。它需要 Visual Studio 2017(或带有更新编译器的 2015),至少 .NET framework 4.5 并使用 Nuget 包管理器添加 System.Memory 包。

var span = new Span<byte>(arr, 3, arr.Length - 3);
ushort crc = ComputeChecksum(span.ToArray());

最直接的解决方案是在您的方法中添加 offsetlength 参数

public static ushort ComputeChecksum(byte[] buffer, int length, int offset)

    ushort index;
    ushort crc = 0;
    for (int i = offset; i < length; ++i)
    
        index = (ushort)((low ^ buffer[i]) & 0x00FF);
        crc = (ushort)((high * 256) ^ table[index]);
    

    return crc;

和用法

int offset = 3;
ushort crc = ComputeChecksum(arr, arr.Length - offset, offset);

【讨论】:

以上是关于C# * 和 & 运算符用于指向数组的主要内容,如果未能解决你的问题,请参考以下文章

C#运算符大全_各种运算符号的概述及作用

用于自己的数据访问的惰性运算符 C#

C++ 对象的动态建立 & 释放

C语言之指针学习

K&R阅读笔记——指针

C#中符号的作用备忘