What's the difference between ptr[i] and *(ptr

2020-04-05 08:47发布

问题:

When using a pointer to an array, I've always accessed the elements by using an indexer, such as, myPtr[i] = stuff; however, I was recently looking over BitConverter's implementation and discovered that elements were accessed by doing, *(myPtr + i) = stuff.

Which I thought was quite odd, since both methods (from what I know) do the exact same thing, that is, they return the address of myPtr + i, except (in my opinion) the indexer method looks much more readable.

So why did Microsoft choose to increment pointers the way they did, what's the difference between the two methods (are there performance benefits)?

回答1:

As you stated, they do the same thing.

In fact, when accessing an int*, both ptr[i] and *(ptr + i) syntaxes will skip the bounds check, and point to some memory outside the array bounds if i is greater than the array length.

I'm pretty sure C#, as well as C++, inherited the indexed access to an array pointer using the *(ptr + index) syntax from C. I'm pretty sure that's the only reason why both syntaxes are available.



回答2:

From CSharp Language Specification (18.5.3):

A pointer element access of the form P[E] is evaluated exactly as *(P + E). (...) The pointer element access operator does not check for out-of-bounds errors and the behavior when accessing an out-of-bounds element is undefined. This is the same as C and C++.

There are no differences.



回答3:

To clarify the difference between [] operator of an array and pointer (which discussed under dcastro's answer), you may check output of below code.

unsafe {
    int[] arr = new[] { 1, 2 };
    fixed(int* ptr = arr) {
        for(int i = 0; i < arr.Length + 1; i++) {
            try { System.Console.WriteLine(*(ptr + i)); } catch(Exception e) { System.Console.WriteLine(e.Message); }
            try { System.Console.WriteLine(ptr[i]); } catch (Exception e) { System.Console.WriteLine(e.Message); }
            try { System.Console.WriteLine(arr[i]); } catch (Exception e) { System.Console.WriteLine(e.Message); }
        }
    }
}

Output

1
1
1
2
2
2
0
0
Index was outside the bounds of the array.