C for循环中变量增加的奇怪行为
编辑:这不是我的代码,这是考试的一部分 这是输出:C for循环中变量增加的奇怪行为,c,C,编辑:这不是我的代码,这是考试的一部分 这是输出: 60-3//从-5到-3 59 0//从-3到0 58.3 57.6 2 我不明白为什么在第一个循环中,“I”变量增加了两倍,在第二个循环中增加了三倍 int a=61,i=-5; for(int *p=&i;(a++,(*p)++)?(++(*p),(a--)-1):((*p)+=3,a-1);(*p)++){ --a; printf("%d %d \n",a,*p); if(*p>3){
60-3//从-5到-3
59 0//从-3到0
58.3
57.6
2
我不明白为什么在第一个循环中,“I”变量增加了两倍,在第二个循环中增加了三倍
int a=61,i=-5;
for(int *p=&i;(a++,(*p)++)?(++(*p),(a--)-1):((*p)+=3,a-1);(*p)++){
--a;
printf("%d %d \n",a,*p);
if(*p>3){
a=(!(--a)&&a++)?3:2;
break;
}
else continue;
}
printf("%d\n",a);
for循环声明末尾的
(*p)+
语句将不会在第一次迭代中执行。它只在两次连续迭代之间执行。首先,inta=61,i=-5
给我们提供了a
=61和i
=−五,
然后,int*p=&i
的的初始子句将p
设置为指向i
。从这一点开始,我们可以将*p
等同于i
然后计算,(a++,(*p)++)?(++(*p),(a-)-1):((*p)+=3,a-1)
的的控制表达式。其最高/最外层运算符是?:代码>。计算(a++,(*p)+)+
的第一个操作数。这会将a
设置为62,将i
设置为62−4.逗号运算符的结果是增量之前的i
(*p
)值,因此−五,
那−5用于在中选择:代码>操作。因为它不是零,所以计算?
和:
之间的操作数。那就是(++(*p),(a-)-1)
。这将i
设置为−3和a
至61。增量减1之前的值为a
,即62−1 = 61. 因此,表达式为非零,表示循环应继续
程序控制流入
的主体,其中--a
将a
减至60
然后,printf
告诉我们,a
是60,i
是60−三,
测试*p>3
为假,因为i
为假−3,因此执行continue
这将导致对
的
的迭代表达式求值。即(*p)+
,因此i
设置为−二,
然后计算控制表达式。与前面一样,的第一个操作数:代码>,(a++,(*p)++)
,进行计算。这会将a
设置为61,将i
设置为−1,表达式的值为−二,
再次计算第二个操作数(++(*p),(a--)-1。这将i
设置为0,a
设置为60,其值为59
在车身内部,--a
将a
减至59
printf
显示a
为59,i
为0
同样,*p>3
为假,因此执行继续
这将控制迭代表达式,(*p)+
,它将i
设置为1
然后从的第一个操作数开始计算控制表达式:代码>。现在(a++,(*p++)
将a
设置为60,将i
设置为2,表达式值为1
的第二个操作数:计算代码>,(++(*p),(a-)-1),将i
设置为3,a
设置为59,表达式值为59,因此循环继续
--a
将a设置为58
printf
显示a
为58,i
为3
同样,*p>3
为假,因此执行继续
这将控制迭代表达式,(*p)+
,它将i
设置为4
然后从的第一个操作数开始计算控制表达式:代码>。现在(a++,(*p++)
将a
设置为59,将i
设置为5,表达式值为4
的第二个操作数:计算代码>,(++(*p),(a-)-1),将i
设置为6,a
设置为58,表达式值为58,因此循环继续
--a
将a设置为57
printf
显示a
为57,i
为6
现在*p>3
为真,因此执行if
中的语句
它们以a=(!(-a)和&a++)3:2开始代码>。此处--a
将a
设置为56,并计算为该值。然后代码>逻辑反转,生成0。这会导致&&
生成0,而不计算其第二个操作数。所以的第一个操作数是:
为0,这将导致第三个操作数?:代码>正在评估。该操作数是2,因此这是分配给a
的值
最后的printf
向我们显示了a
,2的当前值。对这样的代码唯一明智的做法是重写它(除了向作者说出此处不允许的单词)。可以删除否则继续
。它一事无成
然后我们看野兽(a++,(*p)++)?(++(*p),(a-)-1):((*p)+=3,a-1)
。这将在每个循环的开头执行,因此我们可以这样重写它:
bool cond = (a++,(*p)++)?(++(*p),(a--)-1):((*p)+=3,a-1);
for(int *p=&i; cond; (*p)++){
cond = (a++,(*p)++)?(++(*p),(a--)-1):((*p)+=3,a-1);
--a;
printf("%d %d \n",a,*p);
if(*p>3){
a=(!(--a)&&a++)?3:2;
break;
}
}
现在,当它从收割台上拆下时,我们可以开始拆解它了。首先,将EXTRACTa++
更改为if语句:
a++;
if((*p)++)
cond = (++(*p),(a--)-1)
else
cond = ((*p)+=3,a-1);
看起来已经清楚多了。现在,让我们去掉那些逗号:
if((*p)++) {
++(*p);
cond = (a--)-1;
}
else {
(*p)+=3;
cond = a-1;
}
让我们继续分离
if((*p)++) {
(*p)++; // Does not make a difference here, but it's easier to not mix pre and post
a--;
cond = a;
}
else {
(*p)+=3;
cond = a-1;
}
这就是我们通过机械地分解它所能达到的程度。为了更进一步,我们需要想一想。那么让我们继续下一步,即a=(!(-a)&&a++)3:2代码>我们也将简化它
--a; // Will be executed no matter what
if(!a) {
a++; // Will only be executed if !(--a) evaluates to true
a = 3; // But it does not matter since we are reassigning a
} else {
a = 2;
}
这将在简化后给出此代码
bool cond;
a++;
if((*p)++) {
(*p)++;
a--;
cond = a;
} else {
(*p)+=3;
cond = a-1;
}
for(int *p=&i; cond; (*p)++){
a++;
if((*p)++) {
(*p)++;
a--;
cond = a;
} else {
(*p)+=3;
cond = a-1;
}
--a;
printf("%d %d \n",a,*p);
if(!a) {
a = 3;
} else {
a = 2;
}
}
printf("%d\n",a);
现在,我们可以对其进行推理了,只需在纸上一步一步地执行该代码就相当容易了。该代码实际上是无法理解的。让您的目标是编写不仅编译器能够理解的代码,而且