Jaka jest różnica między memcpy()
i strcpy()
? Próbowałem go znaleźć za pomocą programu, ale oba dają ten sam wynik.
int main()
{
char s[5]={'s','a','\0','c','h'};
char p[5];
char t[5];
strcpy(p,s);
memcpy(t,s,5);
printf("sachin p is [%s], t is [%s]",p,t);
return 0;
}
Wynik
sachin p is [sa], t is [sa]
Odpowiedzi:
Skompiluj i uruchom ten kod:
void dump5(char *str); int main() { char s[5]={'s','a','\0','c','h'}; char membuff[5]; char strbuff[5]; memset(membuff, 0, 5); // init both buffers to nulls memset(strbuff, 0, 5); strcpy(strbuff,s); memcpy(membuff,s,5); dump5(membuff); // show what happened dump5(strbuff); return 0; } void dump5(char *str) { char *p = str; for (int n = 0; n < 5; ++n) { printf("%2.2x ", *p); ++p; } printf("\t"); p = str; for (int n = 0; n < 5; ++n) { printf("%c", *p ? *p : ' '); ++p; } printf("\n", str); }
Spowoduje to:
73 61 00 63 68 sa ch 73 61 00 00 00 sa
Widać, że „ch” zostało skopiowane przez
memcpy()
, ale niestrcpy()
.źródło
printf("%2.2x ", *p);
- dlaczego ograniczyłeś printf do 2.2? Poza tym wcale NIE widzę kropki ... Po drugie -printf("%c", *p ? *p : ' ');
- co tak naprawdę sprawdza ten test? Jeśli*p
? Dziękuję z góry za Twoją odpowiedź!*p
środki testowe: „Jeśli trafisz null, wydrukować przestrzeni”.strcpy
zatrzymuje się, gdy napotka znak NUL ('\0'
),memcpy
nie. Nie widać tu efektu, ponieważ%s
printf również zatrzymuje się na NUL.źródło
p
it
do czegoś (na przykład wszystkie spacje), a następnie po skopiowaniu porównajp[3]
zt[3]
.strcpy
Nie wykracza poza top[2]
, gdzie stwierdzono charakter zerową, alememcpy
jako skierowane kopiowane pięć znaków.strcpy
kończy się, gdy zostanie znaleziony zerowy terminator ciągu źródłowego.memcpy
wymaga przekazania parametru rozmiaru. W przypadku, gdy przedstawiłeś,printf
instrukcja zatrzymuje się po znalezieniu terminatora null dla obu tablic znaków, jednak znajdzieszt[3]
it[4]
skopiujesz również dane w nich.źródło
strcpy
kopiuje jeden po drugim znak ze źródła do celu, aż znajdzie znak NULL lub „\ 0” w źródle.while((*dst++) = (*src++));
gdzie jako
memcpy
kopiuje dane (nie znak) ze źródła do miejsca przeznaczenia o danym rozmiarze n, niezależnie od danych w źródle.memcpy
powinno być używane, jeśli dobrze wiesz, że źródła zawierają inne elementy niż znak. w przypadku danych zaszyfrowanych lub danych binarnych memcpy jest idealnym rozwiązaniem.strcpy
jest przestarzały, więc użyjstrncpy
.źródło
Ze względu na pusty znak w
s
ciąguprintf
nie pokaże niczego poza tym. Różnica międzyp
it
będzie w postaci 4 i 5.p
nie będzie miała żadnego (będą śmieci) it
będzie miała'c'
i'h'
.źródło
strcpy
zatrzymuje się, gdy napotkaNULL
lub'\0'
memcpy
jest zwykle bardziej wydajna niż tastrcpy
, która zawsze skanuje dane, które kopiujeźródło
Główna różnica polega na tym, że
memcpy()
zawsze kopiuje dokładnie określoną liczbę bajtów;strcpy()
z drugiej strony będzie kopiować, dopóki nie odczyta bajtu NUL (znanego również jako 0), a następnie zatrzyma się.źródło
Problem z twoim programem testowym polega na tym, że
printf()
przestaje wstawiać argument do%s
, gdy napotka zakończenie zerowe\0
. Więc w swoim wyjściu prawdopodobnie nie zauważyłeś, żememcpy()
skopiowałeś znakic
ih
również.Widziałem w GNU
glibc-2.24
, że (dla x86)strcpy()
tylko wywołaniamemcpy(dest, src, strlen(src) + 1)
.źródło
printf("%s",...)
zatrzymuje drukowanie danych po napotkaniu wartości null, więc oba wyjścia są takie same.Poniższy kod rozróżnia
strcpy
imemcpy
:#include<stdio.h> #include<string.h> int main() { char s[5]={'s','a','\0','c','h'}; char p[5]; char t[5]; int i; strcpy(p,s); memcpy(t,s,5); for(i=0;i<5;i++) printf("%c",p[i]); printf("\n"); for(i=0;i<5;i++) printf("%c",t[i]); return 0; }
źródło