如果我运行以下代码,graph[0][0]
获得1
而graph[0][1]
获得4
。
换句话说,行graph[0][++graph[0][0]] = 4;
将1
放入graph[0][0]
,将4
放入graph[0][1]
。
如果有人能提供合理的解释,我真的很感激。
我从Visual C ++ 2015以及Android C编译器(CppDriod)中观察到了这一点。
static int graph[10][10];
void main(void)
{
graph[0][++graph[0][0]] = 4;
}
答案 0 :(得分:5)
让我们分解一下:
++graph[0][0]
这会预先增加graph[0][0]
处的值,这意味着现在为graph[0][0] = 1
,然后表达式的值为1
(因为这是{{1}的最终值}})。
然后,
graph[0][0]
基本上,graph[0][/*previous expression = 1*/] = 4;
就是这样!现在graph[0][1] = 4;
和graph[0][0] = 1
。
答案 1 :(得分:2)
首先让我们看看一元(前缀)增量运算符是什么。
前缀++运算符的操作数的值递增。结果是增量后操作数的新值。
所以,在
的情况下graph[0][++graph[0][0]] = 4;
首先,graph[0][0]
的值加1,然后该值用于索引。
现在,graph
是一个静态全局变量,由于隐式初始化,默认情况下,数组中的所有成员都被初始化为0
。因此,++graph[0][0]
会将graph[0][0]
的值增加为1,并返回1
的值。
然后,指令的简化版本看起来像
graph[0][1] = 4;
因此,你得到了
graph[0][0]
为1 graph[0][1]
为4。另外,FWIW,main()
的推荐签名是int main(void)
。
答案 2 :(得分:1)
您通过执行graph[0][0]
向++graph[0][0]
添加一个。然后将graph[0][1]
设置为4
。也许你想做graph[0][graph[0][0]+1] = 4
答案 3 :(得分:1)
首先,您的变量graph[10][10]
是静态的,因此它将使用值0
进行初始化。
然后在{strong> graph [0] [0] = 0 行graph[0][++graph[0][0]] = 4 ;
,只需递增 graph [0] [0] 的值,基本上你自己分配graph[0][1] = 4;
请注意,您已经使用了预增量运算符(++ x),因此它首先会增加并且值会更改但是如果您使用后增量运算符(x ++)则graph[0][0] = 4;
本身< /强>
答案 4 :(得分:0)
让我们排列关于这个表达的事实
graph[0][++graph[0][0]] = 4;
根据6.5.1,在计算数组元素++graph[0][0]
之前对数组索引graph[0][++graph[0][0]]
的计算进行排序,然后在计算整个赋值运算符之前对其进行排序。
++graph[0][0]
的值必须为1
。请注意,这并不意味着整个预增量及其副作用必须首先发生&#34;。它只是意味着必须首先计算该预增量的结果(1
)。 graph[0][0]
的实际修改(即graph[0][0]
从0
更改为1
)可能会在很晚之后发生。没有人知道它何时会发生(在声明结束之前的某个时间)。
这意味着赋值运算符修改的元素为graph[0][1]
。这是4
应该去的地方。将4
分配给graph[0][1]
也是=
运算符的副作用,这将在语句结束之前的某个时间发生。
请注意,在这种情况下,我们可以最终确定++
修改graph[0][0]
,而=
修改graph[0][1]
。我们有两个未经测试的副作用(这是危险的),但它们作用于两个不同的物体(这使它们安全)。在这种情况下,这正是使我们免于未定义行为的原因。
但是,这取决于graph
数组的初始值。如果你试试这个
graph[0][0] = -1;
graph[0][++graph[0][0]] = 4;
即使表达式本身看起来相同,行为也会立即变为未定义。在这种情况下,++
的副作用和=
的副作用将应用于同一数组元素graph[0][0]
。副作用相互之间没有排序,这意味着行为未定义。