while(* p2 ++ = * p1 ++); 意思?

我有一个代码块:

int main () { char *p1 = "Hello"; char *p2; p2 = (char*)malloc (20); memset (p2, 0, 20); while (*p2++ = *p1++); printf ("%s\n", p2); } 

但我无法解释该行的工作(* p2 ++ = * p1 ++); 你能让我知道这个公式中的操作顺序吗?

它是经典的C代码,通过将所有内容放在一行中来试图看起来非常聪明。

while (*p2++ = *p1++); 相当于

 strcpy(p2, p1); p1 += strlen(p1) + 1; p2 += strlen(p2) + 1; 

换句话说,它复制一个以空字符结尾的字符串,其中p1最后指向源字符串的末尾, p2指向目标字符串的末尾。

这是一个字符串副本,但您丢失了原始指针值。 您应该保存原始指针值。

 int main () { char *p1 = "Hello"; char *p2 = malloc(20); char *p3 = p2; memset (p2, 0, 20); while (*p2++ = *p1++); printf ("%s\n", p3); } 

while循环的实际语义解释如下:

 for (;;) { char *q2 = p2; // original p2 in q2 char *q1 = p1; // original p1 in q1 char c = *q1; // original *p1 in c p2 += 1; // complete post increment of p2 p1 += 1; // complete post increment of p1 *q2 = c; // copy character *q1 into *q2 if (c) continue; // continue if c is not 0 break; // otherwise loop ends } 

保存q1q2的顺序以及p2p1递增的顺序可以互换。 保存*q1 ,可以在任何时候保存*q1c 。 保存c后,可以在任何时候分配c*q2 。 在我的信封背面,这至少有40种不同的解释。

while循环正在评估表达式: *p2++ = *p1++while循环表达式:
*p2 = *p1使用*p1的结果进行评估。 但是,即使表达式的计算结果为false(0) ,该值仍会分配给*p2 。 重写这个:

 char c; do { c = *p1; /* read the src byte */ *p2 = c; /* write to dst byte */ p2++, p1++; /* increment src, dst pointers */ } while (c != 0); 

您会注意到读/写将至少发生一次。 没关系,只要C字符串p1是nul终止的,并且p2有足够的存储空间用于C字符串。 也就是说, malloc应该至少分配strlen(p1) + 1个字节。 在提供的代码中,这是真的。

正如其他人所指出的那样,最后的迭代会将p1保留在一个接一个地址的地址,这仍然是一个有效的指针,但在取消引用时会有未定义的结果。 p2的地址既是有效指针又是有效的解引用,因为你要分配20个字节。 但是, p2不再指向C字符串副本。 你想要的是一个相当于:

 char *p1 = "Hello"; char *p2, *tmp; p2 = (char*)malloc (20); memset (p2, 0, 20); tmp = p2; while (*tmp++ = *p1++); printf ("%s\n", p2); 

大多数操作系统将在从main退出时释放p2的内存,但最好通过相应的调用来解除资源:

 free(p2); 

在末尾。 在良好实践的主题上,您还应检查malloc的返回值以确保分配成功。