我知道这个问题已经被讨论了很多次,但今天我遇到了一个情况,使我对指针运算/数组索引的理解产生了震撼。
一直以来,我都认为&mybuff[10] 和 (&mybuff+10) 是引用同一块内存的等效方式。
然而,今天早上我花了很长时间来处理一个问题:
memcpy(&mybuff+10,&in,8);
使用优化编译时,缓冲区溢出了,但在调试编译时却可以正常工作。
同时,
memcpy(&mybuff[10],&in,8);
在这两种情况下都很好地工作。
非常感谢任何想法或指针。
mybuff
创造一个声明。char mybuff[123];
&mybuff+10
对类型为“指向123个字符数组的指针”的&mybuff
进行指针运算。这与纯粹的mybuff
不同,后者(经过指针衰减)具有类型“指向char的指针”。这两个表达式的位值是相同的,但由于它们是指向不同大小的物品的指针,所以它们在指针算术下的行为不同。
&mybuff+10
表示您想要跨越类型中的十个123-char数组(鉴于声明而言无意义并且可能导致段错误),而mybuff+10
只表示想要跨越十个单独的字符。&mybuff+10
类似于(&mybuff)+10
&mybuff[10]
类似于&(mybuff[10])
&mybuff[10]
相当于&mybuff[0] + 10
,也就是mybuff + 10
数组索引是基于指针算术定义的。p[i]
意味着*(p+i)
(如果p
或i
是一个更复杂的表达式,则忽略需要额外的括号),其中p
是指针值,i
是整数值。
趣闻:由于加法,即使是指针+整数加法,也是可交换的,所以p[i]
也可以写成i[p]
。 是的,4["Hello"] == 'o'
。为了未来阅读你的代码的人,请不要利用这个知识。
C语言中数组和指针之间关系的优秀参考资料(C++中规则几乎相同)是comp.lang.c FAQ的第6部分。(我可以直接链接到第6部分,但我喜欢鼓励人们去浏览它;整个内容都值得一读。)
我认为你遇到了指针问题。
如果mybuff是一个指针,那么mybuff + 10 == &(mybuff[10])
。
这与你写的&mybuff + 10
不同。
(&mybuff+10)
和&mybuff[10]
并不等价,但是&mybuff[10]
和mybuff + 10
是等价的。
&mybuff[10]
解析为&(mybuff[10])
,这被计算为&(*(mybuff + 10))
。 - John Bodemybuff + 10
相等。 - Janick Bernet&mybuff[10]
有一个定义行为,那么它的行为就与mybuff+10
相同。然而,如果mybuff是一个由10个元素组成的数组,那么在&mybuff[10]
中隐含的解引用已经超出了对象的末尾,并且可能会触发未定义的行为(虽然我认为我曾经看到其他人争辩说当*foo
被地址运算符立即使用时,它不算作解引用,因此不会触发未定义行为),而mybuff+10
则是有定义的。 - hmakholm left over Monicamybuff+10
而不是&mybuff+10
,后者表示将移动到数组中的第10个位置并复制8个字节(根据您的memcpy语句)。但仍然不确定是否能够容纳额外的8个字节。
&mybuff[10]
的计算结果为&(*(mybuff+10))
,这与&mybuff + 10
不同。请记住,像[]
这样的后缀运算符比像&
这样的一元运算符具有更高的优先级。 - John Bode