我有一个代码块:
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++)这条线的工作原理;你能告诉我这个公式中的运算顺序吗?
发布于 2013-05-16 15:08:48
这是一段经典的C代码,试图通过将所有内容放在一行中而看起来非常聪明。
while (*p2++ = *p1++);
等同于
strcpy(p2, p1);
p1 += strlen(p1) + 1;
p2 += strlen(p2) + 1;
换句话说,它复制一个以null结尾的字符串,其中p1
指向源字符串的末尾,p2
指向目标字符串的末尾。
发布于 2013-05-16 15:11:34
这是一个字符串副本,但您正在丢失原始指针值。您应该保存原始的指针值。
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种不同的解释。
发布于 2013-05-16 16:12:55
while
循环正在计算表达式:*p2++ = *p1++
。while
循环表达式:
使用*p1
的结果来评估*p2 = *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
的返回值,以确保分配成功。
https://stackoverflow.com/questions/16581048
复制相似问题