- 此问题在此处已有答案**:
With arrays, why is it the case that a[5] == 5[a]?(20个答案)
三年前关闭了。
今天我无意中发现了一个让我大吃一惊的谜语。
我没想到下面例子中的-1 [p]会编译,但它编译成功了,事实上,x最终是-3。
int x;
int array[] = {1, 2, 3};
int *p = &array[1];
x = -1[p];
我在互联网上搜索了类似-1 [pointer]的东西,但是什么也没找到。好吧,我承认输入正确的搜索查询很困难。谁知道为什么-1 [p]编译后X变成了-3?
5条答案
按热度按时间b1payxdu1#
我是制作这个“谜语”的人(请参见my Twitter post)
那么,-1[p]是怎么回事?
ISO C实际上将[]定义为对称的,这意味着
x[y]
与y[x]
相同,其中x和y都是表达式。我们可能会天真地得出
-1[p]
是p[-1]
,x = 1
的结论。然而,-1实际上是应用于常数1的一元减运算符,并且一元减的优先级低于[]因此,
-1[p]
等于-(p[1])
,得到-3。这也会导致类似下面这样的时髦片段:
sizeof(char)["abc"] /* yields 'b' */
cvxl0en22#
首先要弄清楚的是优先级,也就是说
[]
比一元运算符的优先级高,所以-1[p]
等于-(1[p])
,而不是(-1)[p]
,所以我们取1[p]
的结果并求反。x[y]
等于*(x+y)
,所以1[p]
等于*(1+p)
,*(1+p)
等于*(p+1)
,*(p+1)
等于p[1]
。我们取
p
指向的第一个元素,也就是array
的第三个元素,也就是3,然后取反,得到-3
。jexiocij3#
根据C标准(6.5.2后缀运算符),下标运算符按以下方式定义
因此,方括号前应有一个后缀表达式。
在此表达式语句中
使用了后缀表达式
1
(同时也是主表达式)、后缀表达式1[p]
(也就是下标运算符)和一元运算符-
。考虑到当编译器将程序拆分为标记时,整数常量被认为是没有减号的标记本身。减号是单独的标记。所以这个语句可以重写为
因为后缀表达式比一元表达式具有更高的优先级。
我们首先考虑后缀子表达式
1[p]
根据C标准(6.5.2.1数组下标)
2一个后缀表达式后面跟一个方括号[]中的表达式是数组对象的一个元素的下标指定。下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))。由于应用于二元运算符+的转换规则,如果E1是数组对象(相当于指向数组对象初始元素的指针)且E2是整数,则E1[E2]指定E1的第E2个元素(从零开始计数)。
因此,此子表达式的计算结果类似于
*( ( 1 ) + ( p ) )
,并且与*( ( p ) + ( 1 ) ).
相同因此上述声明
相当于
并将生成
-3
,因为由于语句,指针p
指向数组的第二个元素然后表达式
p[1]
得出数组第二个元素之后的元素的值,然后应用一元运算符-
。wecizke34#
这个
看起来像
下一次当你喜欢
整数指针
p
指向array[1]
的地址,即0x104
。如下所示当你喜欢的时候
-1[p]
等价于-(1[p])
,即-(p[1])
。它看起来像qv7cva1a5#
这里发生的事情真的很有趣。
p[n]表示
*(p+n)
,这就是为什么您看到3,因为“p”指向数组[1],数组[1]的值为2,而-p[1]被解释为-(*(p+1))
,它的值为-3。