指针条件while(* s1 ++ = * s2 ++)

int main() { char str1[] = "Overflow"; char str2[] = "Stack"; char *s1 = str1, *s2=str2; while(*s1++ = *s2++) printf("%s", str1); return 0; } 

当这种情况破裂时

 (while(*s1++ = *s2++)) 

请解释逻辑

输出来了

在此处输入图像描述

*s1++ ,在此变量中, *优先级高于++ 。 在下面的代码中,

 while(*s1++ = *s2++); //There should be a semicolon.Your code does not has. 
  1. 首先评估*s1 = *s2
  2. 几乎C中的每个表达式都返回一个值。 所以*s1 = *s2返回的值是第一个字符,显然不是null。 while()循环执行。
  3. 然后s1s2递增。
  4. s2到达字符串的末尾时, *s2返回分配给s1 '\0'*s1=*s2 。 现在这个表达式也返回一个值为'\0'while('\0')循环终止。

这个while循环依赖于非零在C中的任何条件表达式中求值为true的事实。

从另一种方式开始,从更明显的方式进行操作,到这种速记,可能更清楚。

你可以从:

 while(*s2 != '\0') { *s1 = *s2; s1++; s2++; } 

这意味着’当s2没有到达终止符时,继续将字符从s2复制到s1。 在每个副本之后向前移动两个指针以准备下一个副本。

但是,这可以通过将增量操作包含在与副本相同的行中来缩短。 这是安全的,因为它是一个后增量操作。 在副本完成之前,它不会评估。 代码现在看起来像这样:

 while(*s2 != '\0') { *s1++ = *s2++; } 

现在,假设非零等于真,我们可以进一步简化。 * s2!=’\ 0’本身就相当于* s2。

 while(*s2) { *s1++ = *s2++; } 

最后,我们可以将副本本身移动到while语句中。 while语句本身会将字符从* s2复制到* s1,然后像以前一样评估* s1。 然后增量发生,然后围绕它。 所以我们的代码看起来像这样:

 while(*s1++ = *s2++); 

所以..在你的情况下,你的while语句后需要一个分号,否则它将打印多次。

*运算符的优先级高于++运算符,因为在您的表达式中

 while(*s1++ = *s2++) 

s1在增量之前首先由s2分配,因此评估的顺序将是

1. *s1=*s2;

2. s1++,s2++

3 printf("%s",str1) ,这里str1的值因操作1而改变

4.当环到达'\0'时,循环处理条件到来,由于上面指定的*s1=*s2 ,该值被分配给s1, *s1=*s2值变为null => s1='\0'并且循环得到终止

这个循环会将str2内容复制到str1

 while(*s1++ = *s2++); 

如果它会在str2中遇到最后一个字节时停止(这将是0)。

换句话说, str1[] = "Overflow"将变为str1[] = "Stacklow"


更新 :更详细的解释。

  • 在第一个循环中,您只从str2复制1个字符,即S 所以来自Overflow str1变成了Sverflow
  • 第二个循环,它变成Sterflow
  • 第三个循环,它变成了Starflow
  • 第四个循环,它变成了Stacflow
  • 第五个循环,它变成Stacklow

请注意,这些是截图中可见的线条。

之后,遇到0字节并复制到str1 ,因此它变为Stack\0ow ,但是你不打印它。 如果你打印它,它将打印只是Stack

它会循环,直到遇到s2中的字符串终止符(’\ 0’)

 while(*s1++ = *s2++) printf("%s", str1); while(*s1++='S') prints "Sverflow" while(*s1++='t') prints "Sterflow" while(*s1++='a') prints "Starflow" while(*s1++='c') prints "Stacflow" while(*s1++='k') prints "Stacklow" while(*s1++='\0') ends loop