Pętla while
oblicza wyrażenie: *p2++ = *p1++
. Wyrażenie pętli while
:
*p2 = *p1
jest oceniane przy użyciu wyniku *p1
. Jednak ta wartość jest nadal przypisana do *p2
, nawet jeśli wyrażenie jest oceniane jako false
lub (0)
. Przepisanie to:
char c;
do
{
c = *p1; /* read the src byte */
*p2 = c; /* write to dst byte */
p2++, p1++; /* increment src, dst pointers */
}
while (c != 0);
Można zauważyć, że do odczytu/zapisu nastąpi przynajmniej raz. To jest w porządku, o ile ciąg C p1
jest zakończony nulem, a p2
ma wystarczającą ilość miejsca na ciąg C. To znaczy, malloc
powinien przydzielić co najmniej strlen(p1) + 1
bajtów. Podany kod jest prawdziwy.
Jak inni zwrócili uwagę, ostateczna iteracja pozostawi p1
pod adresem jeden-past-the-end, który jest nadal ważny wskaźnik, ale niezdefiniowane wyniki podczas dereferencjonowane. Adres p2
jest prawidłowym wskaźnikiem i prawidłowym dereferencją, ponieważ przydzielasz 20 bajtów. Jednakże, p2
nie wskazuje już na ciąg znaków C.Co chcesz jest odpowiednikiem:
char *p1 = "Hello";
char *p2, *tmp;
p2 = (char*)malloc (20);
memset (p2, 0, 20);
tmp = p2;
while (*tmp++ = *p1++);
printf ("%s\n", p2);
większości systemów operacyjnych będzie zwolnić pamięć w p2
na wyjściu z main
, ale jest to dobra praktyka, aby rozwijać zasoby z odpowiednim wywołaniu:
free(p2);
na końcu. W kwestii dobrych praktyk powinieneś również sprawdzić wartość zwracaną przez malloc
, aby upewnić się, że alokacja się powiedzie.
[Jak działa "while (* s ++ = * t ++)"? (Http://stackoverflow.com/q/810129/4279) – jfs