2

I'm trying to compare 2 byte array using pointers. I treat the byte arrays as int pointer to run things faster(compare 4 bytes together).

    public static bool DoBuffersEqual(byte[] first, byte[] second)
    {
        unsafe
        {
            fixed (byte* pfirst = first, psecond = second)
            {
                int* intfirst = (int*)pfirst;
                int* intsecond = (int*)psecond;

                for (int i = 0; i < first.Length / 4; i++)
                {
                    if ((intfirst + i) != (intsecond + i))
                        return false;
                }
            }
        }
        return true;
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        byte[] arr1 = new byte[4000];
        byte[] arr2 = new byte[4000];
        for (int i = 0; i < arr1.Length; i++)
        {
            arr1[i] = 100;
            arr2[i] = 100;
        }
        bool res = DoBuffersEqual(arr1, arr2);
        Console.WriteLine(res);
    }

For some reason i'm getting False result after calling this function...

Does anybody have any idea what's wrong here?

Thanks in advance!

Slashy
  • 1,691
  • 1
  • 16
  • 40
  • Possible duplicate of [Checking equality for two byte arrays](http://stackoverflow.com/questions/18472867/checking-equality-for-two-byte-arrays) – Smartis Apr 03 '17 at 11:14
  • 3
    You're comparing the pointers, not the pointed to values. So : `if (*(intfirst + i) != *(intsecond + i))` – spender Apr 03 '17 at 11:16
  • 1
    You don't dereference your pointers so you are comparing pointers not values they point to. – Evk Apr 03 '17 at 11:17
  • @spender ooops...your right... haha thanks – Slashy Apr 03 '17 at 11:17
  • Something for you to consider: this would be a great fit for `Vector` and SIMD, so that on modern CPUs you can compare much wider chunks at a time (32 bytes = 256 bits on my AVX i7). The tricky bit is loading the values - `Unsafe.Read` is your friend there. Also, remember to check `Vector.IsHardwareAccelerated` - if it is `false`, don't use it; and check `Vector.Count` to check the local hardware-specific SIMD support to know your stride size. And even if you don't like SIMD: you can still have the op-count by using `long` rather than `int`. – Marc Gravell Apr 03 '17 at 11:20
  • This will fail miserably if the byte array length does not align with `4`. Your are swallowing all the trailing items that don't align. – InBetween Apr 03 '17 at 11:45

1 Answers1

2

As other comments have already stated, the problem is that you are comparing pointers, not values. The correct code should be:

if (*(intfirst + i) != *(intsecond + i))

But I'd like to point out a deeper issues in your code.

  • If the input byte arrays have lengths that don't align with 4 (first.Length % 4 != 0) you will get false positives because you'll be essentially swallowing all misaligned items:

    {1, 2, 3, 4, 5}
    {1, 2, 3, 4, 7}
    

    Will return true when they are obviously not the same.

  • You should be checking, before anything else, that both arrays have the same length and bailing out fast if they don't. You'll run into all kind of issues otherwise.

    {1, 2, 3, 0}
    {1, 2, 3}
    

    Will also return true when it shoudn't.

InBetween
  • 30,991
  • 3
  • 46
  • 80