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

时间:2013-05-16 07:07:27

标签: c

我有一个代码块:

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

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

3 个答案:

答案 0 :(得分:18)

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

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

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

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

答案 1 :(得分:9)

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

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后,c保存到q1可能会随时发生。 c *q2的分配可以在c保存后随时进行。在我的信封背面,这至少有40种不同的解释。

答案 2 :(得分:1)

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

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留在地址 one-last-the-end ,这仍然是一个有效的指针,但在取消引用时会有未定义的结果。 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);

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

free(p2);

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