4

I want to compare parts of byte[] efficiently - so I understand memcmp() should be used.

I know I can using PInvoke to call memcmp() - Comparing two byte arrays in .NET

But, I want to compare only parts of the byte[] - using offset, and there is no memcmp() with offset since it uses pointers.

int CompareBuffers(byte[] buffer1, int offset1, byte[] buffer2, int offset2, int count)
{
  // Somehow call memcmp(&buffer1+offset1, &buffer2+offset2, count)
}

Should I use C++/CLI to do that?

Should I use PInvoke with IntPtr? How?

Thank you.

Community
  • 1
  • 1
brickner
  • 6,595
  • 3
  • 41
  • 54

5 Answers5

14
[DllImport("msvcrt.dll")]
private static extern unsafe int memcmp(byte* b1, byte* b2, int count);

public static unsafe int CompareBuffers(byte[] buffer1, int offset1, byte[] buffer2, int offset2, int count)
{
    fixed (byte* b1 = buffer1, b2 = buffer2)
    {
        return memcmp(b1 + offset1, b2 + offset2, count);
    }
}

You might also want to add some parameter validation.

Cory
  • 141
  • 1
  • 2
5

C++/CLI will definitely be the cleanest, but this hardly justifies adding C++/CLI to your project if you aren't already using it.

How about Marshal.UnsafeAddrOfPinnedArrayElement(array, offset)?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
3

No matter what you do, you should check that the offset/count values are valid for the given byte arrays. After you do that, I don't see how just doing a for loop in C# is going to be any slower than P/Invoking a Win32 method. Seems like there would be a lot of overhead in the P/Invoke that it would not be worthwhile.

Also, there is always unsafe C#.

As with all performance questions, you should do your own performance testing. But it sounds to me like you are trying to optimize for performance prematurely.

Bryan
  • 2,775
  • 3
  • 28
  • 40
  • 1
    Optimized `memcmp` uses SIMD instructions to compare 16 bytes per clock cycle (when the buffers are properly aligned) and also provides cache hinting. One you write in C# won't do that. For small lengths, the p/invoke overhead is too much. But larger buffer sizes really win from calling optimized native code. – Ben Voigt Dec 05 '14 at 16:23
2

No need to P/Invoke in C++/CLI. Use pin_ptr<> to pin the array. That gets you a byte*, just add the offset.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

There is one more way

SequenceEqual from System.Linq

 byte[] ByteArray1 = null;
 byte[] ByteArray2 = null;

 ByteArray1 = MyFunct1();
 ByteArray2 = MyFunct2();

 if (ByteArray1.SequenceEqual<byte>(ByteArray2))
 {
    MessageBox.Show("Same");
 }
 else
 {
   MessageBox.Show("Not Equal");
 }