指针运算 vs. 数组索引

12

我知道这个问题已经被讨论了很多次,但今天我遇到了一个情况,使我对指针运算/数组索引的理解产生了震撼。

一直以来,我都认为&mybuff[10] 和 (&mybuff+10) 是引用同一块内存的等效方式。

然而,今天早上我花了很长时间来处理一个问题:

memcpy(&mybuff+10,&in,8); 

使用优化编译时,缓冲区溢出了,但在调试编译时却可以正常工作。

同时,

memcpy(&mybuff[10],&in,8); 

在这两种情况下都很好地工作。

非常感谢任何想法或指针。


11
嘻嘻,对于要求“指点”的双关语感到好笑。 - Daniel
9
【一些提示】 这是一个经典的网络漫画,主要讲述了程序员的工作心得。其中包含多个笑点和黑色幽默。 - mopsled
1
&mybuff[10] 的计算结果为 &(*(mybuff+10)),这与 &mybuff + 10 不同。请记住,像 [] 这样的后缀运算符比像 & 这样的一元运算符具有更高的优先级。 - John Bode
可能是C语言:为什么数组的地址等于其值?的重复问题。 - Jerry Coffin
7个回答

8
为了举例,我将为mybuff创造一个声明。
char mybuff[123];

现在,&mybuff+10 对类型为“指向123个字符数组的指针”的&mybuff 进行指针运算。这与纯粹的mybuff不同,后者(经过指针衰减)具有类型“指向char的指针”。这两个表达式的位值是相同的,但由于它们是指向不同大小的物品的指针,所以它们在指针算术下的行为不同。 &mybuff+10 表示您想要跨越类型中的十个123-char数组(鉴于声明而言无意义并且可能导致段错误),而mybuff+10只表示想要跨越十个单独的字符。

7

5

&mybuff[10]相当于&mybuff[0] + 10,也就是mybuff + 10

数组索引是基于指针算术定义的。p[i]意味着*(p+i)(如果pi是一个更复杂的表达式,则忽略需要额外的括号),其中p是指针值,i是整数值。

趣闻:由于加法,即使是指针+整数加法,也是可交换的,所以p[i]也可以写成i[p]。 是的,4["Hello"] == 'o'。为了未来阅读你的代码的人,请不要利用这个知识。

C语言中数组和指针之间关系的优秀参考资料(C++中规则几乎相同)是comp.lang.c FAQ的第6部分。(我可以直接链接到第6部分,但我喜欢鼓励人们去浏览它;整个内容都值得一读。)


2

我认为你遇到了指针问题。
如果mybuff是一个指针,那么mybuff + 10 == &(mybuff[10])
这与你写的&mybuff + 10不同。


2

(&mybuff+10)&mybuff[10]等价,但是&mybuff[10]mybuff + 10是等价的。


不完全正确;&mybuff[10]解析为&(mybuff[10]),这被计算为&(*(mybuff + 10)) - John Bode
这与 mybuff + 10 相等。 - Janick Bernet
请删除或编辑我们回答的第一行,因为它对初学者不清楚。 - Taras Mazepa
如果我们想完全遵循语言规范,正确的说法应该是,只要&mybuff[10]有一个定义行为,那么它的行为就与mybuff+10相同。然而,如果mybuff是一个由10个元素组成的数组,那么在&mybuff[10]中隐含的解引用已经超出了对象的末尾,并且可能会触发未定义的行为(虽然我认为我曾经看到其他人争辩说当*foo被地址运算符立即使用时,它不算作解引用,因此不会触发未定义行为),而mybuff+10则是有定义的。 - hmakholm left over Monica

1
正确的语法是mybuff+10而不是&mybuff+10,后者表示将移动到数组中的第10个位置并复制8个字节(根据您的memcpy语句)。但仍然不确定是否能够容纳额外的8个字节。

@user12861:请到这里 - http://www.learncpp.com/cpp-tutorial/68-pointers-arrays-and-pointer-arithmetic/ - user195488
我认为这个答案不够清晰。就我个人而言,我至少了解这么多C++。 - user12861
@user12861:我相信原帖作者明白我在说什么。非常清楚。 - user195488

1

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