ptr[i]和*(ptr + i)有什么区别?

6
当使用指向数组的指针时,我总是使用索引器访问元素,例如 myPtr[i] = stuff; 但是,最近在查看 BitConverter 的实现 时,发现通过 *(myPtr + i) = stuff 访问元素。
我认为这很奇怪,因为这两种方法(据我所知)做的事情完全相同,即返回 myPtr + i 的地址。只是(在我看来),索引器方法看起来更易读。
那么,微软为什么选择以这种方式递增指针呢?这两种方法有什么区别(是否有性能优势)?

它们生成相同的IL代码,只是风格不同而已。 - Kris Vandermotten
ToBoolean 方法非常好用。尽管注释与代码不符,但它采用了很棒的 x == 0 ? false : true 模式,而不是使用简单的 x != 0 - CodesInChaos
3个回答

4
正如你所说,它们执行相同的操作。
实际上,在访问int*时,无论是ptr[i]还是*(ptr + i)语法都会跳过边界检查,如果i大于数组长度,则指向一些超出数组边界的内存。
我非常确定C#和C++都从C中继承了使用*(ptr + index)语法对数组指针进行索引访问。我相信这是为什么两种语法都可用的唯一原因。

那么 myPrt[i] 只是语法糖吗?除此之外没有其他区别了吗? - Sam
@Sam 是的,不应该有任何其他区别。 - dcastro
3
使用索引器可以为您提供IOR,如果您正在访问int数组。例如,如果您正在访问int *,那么[index]*(ptr + index)语法都将指向数组外的某些内存。这两种语法都将跳过边界检查。 - dcastro
@dcastro 谢谢,我的错,确实应该更仔细地阅读问题。 - AndreySarafanov
@CodesInChaos 是的,C 有时可能会有点奇怪i[p] 应该被重写为 *(i+p) - dcastro
显示剩余2条评论

2

来自C#语言规范(18.5.3):

形如 P[E] 的指针元素访问会被计算为 *(P + E)。(...) 指针元素访问运算符不会检查越界错误,当访问越界元素时的行为是未定义的。这与 C 和 C++ 相同。

没有区别。


1
为了澄清数组的[]运算符和指针(在dcastro的回答下讨论)之间的区别,您可以检查下面代码的输出。
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); }
        }
    }
}

输出

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接