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 }
保存q1
和q2
的顺序以及p2
和p1
递增的顺序可以互换。 保存*q1
,可以在任何时候保存*q1
到c
。 保存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
的返回值以确保分配成功。