0

私は主に C++ プログラマーですが、暇なときに C# の速度を上げようとしています。変換したい次のC++関数があります-

#define COMPUTE_CRC32(cp,crc) (crc32lookup_table[((unsigned long)crc^(unsigned char)cp)&0xff]^(((unsigned long)crc>>8)&0x00FFFFFF))

unsigned long ComputeCRC32::Update(const void* ptrBytes, long numBytes)
{
    const unsigned char* ptr_data = (const unsigned char*) ptrBytes;

    while ( --numBytes >= 0 )
    {
        unsigned char data_byte = *ptr_data++ ; 

        m_ulCRC = COMPUTE_CRC32( data_byte, m_ulCRC );
    }

    return m_ulCRC;
}

これを行うには多くの方法があることは知っていますが、最善の方法が何であるかを確認したいと思います。これは私がこれまでに作成したものです -

public uint Update(object ptrBytes, int numBytes)
{
    byte * ptr_data = (byte) ptrBytes;

    while (--numBytes >= 0)
    {
        byte data_byte = *ptr_data++;

        m_ulCRC = (GlobalMembersComputeCRC32.crc32lookup_table[((uint)m_ulCRC ^ (byte)data_byte) & 0xff] ^ (((uint)m_ulCRC >> 8) & 0x00FFFFFF));
    }

    return m_ulCRC;
}

ポインタを変換する最良の方法は何ですか? これを C# で書き直すより良い方法はありますか?

4

2 に答える 2

2

C# はポインターを持つ言語ですが、参照もあります (参照は必ずしもアドレスではありません)。C#などの配列byte[]は、C++ でポインターを使用する可能性があるものを表す通常の方法です。

ポインターを使用するには、 を使用しますunsafeunsafeC# で考えている場合、一般的に「安全ではない」ため、避ける傾向があります。代わりに、ランタイムはチェックを実施して、配列内のバッファ オーバーランなどを回避します。代わりに、Crc32 の疑似コードは次のようになります。

public uint Crc32(byte[] data) {
  uint result;
  for (int i= 0; i < data.Length; i++) {
    byte data_byte = data[i];
    result = doCrc(...stuff with data_byte...);
  }
  return result;
}

forループはdata.Length制限チェックとして使用することに注意してください (参照: Eric Gunnerson: Efficiency of iteration over arrays )。これは、配列の長さに対して JIT によって最適化できるためです。個別の長さパラメーターを使用する場合は使用できないため、これは回避する必要があります (または、必要な反復回数が配列の長さよりも小さい可能性がある場合は、長さと組み合わせます)。

于 2013-11-11T21:23:14.297 に答える
0

これらのポインターは、トリッキーなことは何もしていません。それらは単なる配列反復子です。

public uint Update( byte[] ptrBytes, int numBytes )
{
    for( int i = 0; i < numBytes; i++ )
    {
        byte data_byte = ptr_data[i];
        m_ulCRC = ...
    }

    return m_ulCRC;
}
于 2013-11-11T21:14:40.673 に答える